<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>HARSH PRATAP SINGH</title>
      <link>https://harsh-ps-2003.github.io</link>
      <description>Engineer focused on Distributed Systems, Machine Learning, Databases and Cryptography.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://harsh-ps-2003.github.io/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Fri, 31 Jul 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>Living the GitHub Actions Dream</title>
          <pubDate>Fri, 31 Jul 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/living-the-github-actions-dream/</link>
          <guid>https://harsh-ps-2003.github.io/writes/living-the-github-actions-dream/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/living-the-github-actions-dream/">&lt;p&gt;There is something deeply frustrating about watching a CI pipeline spin for 45 minutes when you know the actual work takes maybe 3 minutes. You push a one line fix, grab coffee, check Slack, and the build is still churning away. The green checkmark feels less like validation and more like a hostage release. I have mass cancelled CI runs more times than I can count, and every time I do it I wonder why we collectively decided this was acceptable.&lt;&#x2F;p&gt;
&lt;p&gt;This post is my attempt to document everything I have learned about making Docker builds fast, GitHub Actions efficient, and CI pipelines that do not make you want to mass cancel runs. We will go deep on how Docker layers actually work, why BuildKit changed everything, the dark arts of caching, the Arm situation that everyone is suddenly dealing with, and why Rust builds are their own special circle of CI hell. Along the way I will share the tricks that actually work and the ones that sound good but do not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-even-is-a-docker-layer&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-even-is-a-docker-layer&quot; aria-label=&quot;Anchor link for: what-even-is-a-docker-layer&quot;&gt;What even is a Docker layer?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To understand why Docker builds are slow, you first need to understand what Docker is actually doing when it builds an image. A Docker image is not a single blob of data. It is a stack of layers, where each layer represents a set of filesystem changes. When you run &lt;code&gt;FROM ubuntu:22.04&lt;&#x2F;code&gt;, you are pulling down a base layer. When you run &lt;code&gt;RUN apt-get update&lt;&#x2F;code&gt;, you are creating a new layer on top of that with the changes that command made to the filesystem. Every instruction in your Dockerfile creates a new layer.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;opencontainers&#x2F;image-spec&quot;&gt;OCI image specification&lt;&#x2F;a&gt; defines how these layers work. Each layer is essentially a tarball of filesystem changes, and each layer has a content-addressable hash. This is important because it means two layers with identical contents will have identical hashes, regardless of when or where they were built. The image manifest ties all these layers together and points to a config file that describes how to run the container.&lt;&#x2F;p&gt;
&lt;p&gt;When Docker builds an image, it checks if it already has a layer with the same hash before building it. This is the foundation of Docker caching. If you have already built a layer and nothing has changed, Docker can skip rebuilding it and just reuse the existing one. The problem is that layers form a chain, and if any layer in the chain changes, every layer after it must be rebuilt. This is why the order of instructions in your Dockerfile matters so much.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it like a stack of pancakes where each pancake depends on the one below it. If you want to change the third pancake from the bottom, you have to remove and remake all the pancakes above it. This is why putting your &lt;code&gt;COPY . .&lt;&#x2F;code&gt; instruction early in the Dockerfile is such a disaster for caching. Every time any file in your project changes, that layer changes, which invalidates every layer after it. A change invalidates its layer and every layer after it, a wave that propagates to the end of the chain. How far that wave travels decides how much of the build reruns on every single change.&lt;&#x2F;p&gt;
&lt;p&gt;The union filesystem that Docker uses to combine these layers is clever but has its own quirks. When you delete a file in a later layer, the file is not actually removed from the earlier layer. Instead, a whiteout marker is added that hides the file. This means your image can be larger than you expect if you install something and then delete it in a later layer. The bytes are still there, just hidden.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-buildkit-changed-everything&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-buildkit-changed-everything&quot; aria-label=&quot;Anchor link for: why-buildkit-changed-everything&quot;&gt;Why BuildKit changed everything&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For years, Docker used what is now called the legacy builder. It was simple and it worked, but it had a fundamental limitation. It processed your Dockerfile sequentially, one instruction at a time. Even if two instructions had no dependency on each other, the builder would wait for the first to complete before starting the second. Multi-stage builds helped by letting you define separate build stages, but the builder still processed them one at a time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;moby&#x2F;buildkit&quot;&gt;BuildKit&lt;&#x2F;a&gt; changed this by treating the Dockerfile as a directed acyclic graph rather than a linear sequence. It analyzes the dependencies between instructions and figures out which ones can run in parallel. If your Dockerfile has two independent RUN commands, BuildKit can execute them simultaneously. If you have multiple stages that do not depend on each other, they can build concurrently. This alone can cut build times dramatically for complex Dockerfiles.&lt;&#x2F;p&gt;
&lt;p&gt;At the heart of BuildKit lies a DAG solver that transforms your Dockerfile into an optimized execution plan. BuildKit parses build instructions into something called LLB, which stands for Low Level Build format, creating a dependency graph of all the operations needed to produce your final image. The DAG solver examines each instruction and determines what it depends on. If instruction B needs the output of instruction A, they run sequentially. But if instructions B and C both only depend on A, they can run at the same time once A completes. This dependency analysis happens before any actual building starts, allowing BuildKit to create the most efficient execution plan possible.&lt;&#x2F;p&gt;
&lt;p&gt;This graph based approach is what enables BuildKit to be fully concurrent. Every node in the graph represents a build operation, and BuildKit can execute any nodes that do not have unmet dependencies. It is constantly looking for work it can parallelize, which is why modern container builds can be surprisingly fast when structured properly.&lt;&#x2F;p&gt;
&lt;p&gt;Parallelism happens at three distinct levels. Stage parallelism is the most visible form. When you have multiple stages in a multi-stage Dockerfile that do not depend on each other, BuildKit recognizes this and runs them simultaneously. Consider a typical web application with both frontend and backend components. While your Node.js dependencies are installing and your React app is building, BuildKit is simultaneously compiling your Go backend on a separate thread or CPU core. The final stage waits for both to complete, but you have effectively cut your build time by running these independent workloads in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;Instruction parallelism happens even within a single stage. When you have multiple COPY instructions that do not depend on each other, or when different branches of your build graph can be resolved independently, BuildKit executes them concurrently. This is particularly noticeable when you are copying multiple directories or files that will be processed separately later. BuildKit can fetch all these resources in parallel rather than sequentially, shaving precious seconds off your build time.&lt;&#x2F;p&gt;
&lt;p&gt;The third level is deduplication across concurrent builds. This is perhaps the most clever optimization. BuildKit uses content addressable storage and checksums to identify when different build contexts would produce identical layers. Imagine you are building multiple services that all start from the same base image and run npm ci with identical package.json files. Without deduplication, each service would run its own npm ci, even if they are building simultaneously. But BuildKit is smarter than that. When it detects this situation, the first build starts computing the layer while the others wait. Once the first build completes that npm ci, all the waiting builds immediately use that result and move on. The same operation that would have run three times runs only once. This deduplication happens automatically across concurrent builds on the same runner, whether they are triggered by different developers pushing to the same repository or a docker bake command building multiple targets at once.&lt;&#x2F;p&gt;
&lt;p&gt;But the parallelism is just the beginning. BuildKit introduced a completely new caching model that is far more sophisticated than the legacy builder. The old builder could only cache layers locally or pull them from a registry. BuildKit supports multiple cache backends including local directories, registry images, inline cache metadata, and the GitHub Actions cache. You can even use multiple cache sources simultaneously, falling back from one to another.&lt;&#x2F;p&gt;
&lt;p&gt;The cache mount feature is particularly powerful for builds that download dependencies. Instead of downloading your npm packages or pip dependencies fresh every time, you can mount a persistent cache directory that survives between builds. The syntax looks like &lt;code&gt;RUN --mount=type=cache,target=&#x2F;root&#x2F;.cache&#x2F;pip pip install -r requirements.txt&lt;&#x2F;code&gt;. The cache directory is not part of the final image, so it does not bloat your image size, but it persists between builds so you do not have to redownload everything.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the thing that explains a large fraction of “we enabled caching and it is still slow” complaints. Docker caching is not one cache, it is at least three. There is the layer cache, which is the chain of instructions. There are mount caches, which are directories that persist across builds and cushion the invalidation wave. And there is the image store at &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;docker&lt;&#x2F;code&gt;, which holds pulled base images and built images. The layer cache is what export backends like &lt;code&gt;type=gha&lt;&#x2F;code&gt; or &lt;code&gt;type=registry&lt;&#x2F;code&gt; handle. Mount caches are not part of any layer, so they are never in the export bundle.&lt;&#x2F;p&gt;
&lt;p&gt;This matters because for compiled languages, the mount cache is where the real win lives. When the invalidation wave hits your install step, the whole step reruns. Mount caches are what make the rerun cheap because the package manager finds its downloads and the compiler finds its incremental state. But on a fresh runner with an exported cache, the surviving layers are warm but every mount cache directory starts empty. The one step you needed to be fast runs from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;The Rust scenario makes this concrete. A dependency change costs about 4 seconds when the mounts survive on a persistent builder. With the GitHub Actions cache backend, it costs 164 seconds. With no cache at all, it costs 19 seconds. The export backend was 8 times slower than doing nothing because it paid to import and export layers that the change invalidated anyway, and the state that would have helped was not in the export.&lt;&#x2F;p&gt;
&lt;p&gt;The fundamental problem is that cache mounts cannot be exported. BuildKit does not support saving or loading cache mounts, so they cannot be persisted across builds in CI providers with ephemeral runners. The cache mount directory lives on the Docker host itself and is made available to any build step that needs it in the future. But when the runner is destroyed after the job, the cache mount goes with it.&lt;&#x2F;p&gt;
&lt;p&gt;There is a workaround called the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;reproducible-containers&#x2F;buildkit-cache-dance&quot;&gt;buildkit-cache-dance&lt;&#x2F;a&gt; pattern. The idea is to extract the cache from the previous build and inject it into the current build. You use the GitHub Actions cache to store the contents of your cache mount directories, then restore them before the build and extract them after. It is hacky but it works.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;cache@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ache-mount&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ache-mount-${{ hashFiles(&amp;#39;Dockerfile&amp;#39;) }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;estore Docker cache mounts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;eproducible-containers&#x2F;buildkit-cache-dance@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ache-map&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;var-cache-apt&amp;quot;: &amp;quot;&#x2F;var&#x2F;cache&#x2F;apt&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        &amp;quot;var-lib-apt&amp;quot;: &amp;quot;&#x2F;var&#x2F;lib&#x2F;apt&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The cache dance action works by injecting the cached directories into the builder before the build starts, then extracting them after the build completes. It is not as fast as having the cache mounts persist natively, but it is much faster than starting from scratch every time.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the counterintuitive part. Sometimes the best solution for CI is to remove cache mounts entirely and rely on layer cache instead. Cache mounts introduce non-determinism into layer identity because the mount state becomes part of the layer’s hash. On ephemeral runners where the mount is always empty, BuildKit cannot match the layer against registry cache. Even with a warm registry cache, every layer with a cache mount misses and runs from scratch. Without the cache mount, the layer is fully determined by its inputs. If your lockfile has not changed, BuildKit matches from registry cache and skips the step entirely. The fundamental tension is that cache mounts optimize for warm rebuilds but break cross-machine cache matching. In CI, you often want the opposite, to skip the step entirely via layer cache rather than make it cheaper to run.&lt;&#x2F;p&gt;
&lt;p&gt;There is another gotcha with cache mounts that bites people in monorepos. The cache directory is shared across all builds on the same host. If two builds arrive simultaneously, BuildKit will happily mount the directory to both, processing the build steps concurrently. This is fine for package managers like npm or pnpm that are designed with lock free concurrent cache access in mind. But tools like apt acquire a pessimistic file lock before overwriting system files in place. If two apt commands compete for the same build cache, the loser will fail to acquire the apt lock and exit with an error.&lt;&#x2F;p&gt;
&lt;p&gt;The solution is to change the mount sharing mode. By default, cache mounts use &lt;code&gt;sharing=shared&lt;&#x2F;code&gt;, which allows concurrent access. For tools that cannot tolerate concurrent access, you use &lt;code&gt;sharing=locked&lt;&#x2F;code&gt; to acquire an exclusive lock.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=cache,sharing=locked,target=&#x2F;var&#x2F;cache&#x2F;apt \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,sharing=locked,target=&#x2F;var&#x2F;lib&#x2F;apt \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apt update &amp;amp;&amp;amp; apt-get -y --no-install-recommends install build-essential&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Locked sharing makes builds more consistent and correct at the cost of serialized access to the cache mount. This is an easy tradeoff to make when starting out, but it can quickly become a performance bottleneck as your build volume scales. Builds will begin to queue, average build duration will climb, and so too will your bill if you are paying by the build minute.&lt;&#x2F;p&gt;
&lt;p&gt;This scenario commonly arises in monorepos that contain multiple apps with similarly structured Dockerfiles. Imagine five apps whose Dockerfiles all include a locked cache mount for sccache. A cross cutting commit could trigger a build for all apps and inadvertently create a build queue, with only one app allowed to compile at a time. The simplest fix is to add an explicit namespace with the &lt;code&gt;id&lt;&#x2F;code&gt; field so each app gets its own cache mount.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=cache,target=&#x2F;sccache,sharing=locked,id=myapp \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cargo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;BuildKit also introduced secret mounts for handling sensitive data during builds. Instead of copying your SSH key or API token into the image and then deleting it (which leaves it in an earlier layer), you can mount it temporarily during a single RUN instruction. The secret never touches the filesystem and never ends up in any layer.&lt;&#x2F;p&gt;
&lt;p&gt;To use BuildKit, you either set &lt;code&gt;DOCKER_BUILDKIT=1&lt;&#x2F;code&gt; as an environment variable or use &lt;code&gt;docker buildx build&lt;&#x2F;code&gt; instead of &lt;code&gt;docker build&lt;&#x2F;code&gt;. As of Docker 23.0 released in February 2023, &lt;code&gt;docker build&lt;&#x2F;code&gt; is actually an alias for &lt;code&gt;docker buildx build&lt;&#x2F;code&gt;. Both commands use BuildKit as the build engine. But buildx is a superset of the regular build command. It offers additional functionality like managing builders, debugging capabilities, imagetools for multi-platform manifest manipulation, and Bake for building multiple images in parallel from a single config.&lt;&#x2F;p&gt;
&lt;p&gt;There are four builder types you can use with buildx. The default docker builder uses the Docker daemon’s built-in BuildKit. It works for basic builds but has limited functionality. The docker-container builder runs BuildKit inside a container, which gives you full BuildKit features including advanced caching with registry or remote cache backends and custom BuildKit configuration. The remote builder connects to a BuildKit daemon running on another machine, useful for multi-architecture builds or distributed builds across machines. The kubernetes builder runs BuildKit inside Kubernetes pods, though this requires significant effort to do safely.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-name&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mybuilder&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-driver&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; docker-container&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mybuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The docker-container builder is what you want when you need to specify BuildKit configuration options or use advanced caching features. The &lt;code&gt;docker&#x2F;build-push-action&lt;&#x2F;code&gt; for GitHub Actions uses BuildKit by default, which is one less thing to worry about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-dockerfiles-that-do-not-hate-you&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#writing-dockerfiles-that-do-not-hate-you&quot; aria-label=&quot;Anchor link for: writing-dockerfiles-that-do-not-hate-you&quot;&gt;Writing Dockerfiles that do not hate you&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The single most impactful thing you can do for Docker build performance is to order your Dockerfile instructions correctly. The rule is simple but often violated. Put things that change rarely at the top and things that change frequently at the bottom. Your base image and system dependencies change rarely. Your application code changes constantly. Structure your Dockerfile accordingly.&lt;&#x2F;p&gt;
&lt;p&gt;The payoff of layer ordering equals the cost of the step it protects. Benchmarks across different stacks show the difference between manifest first ordering and putting &lt;code&gt;COPY . .&lt;&#x2F;code&gt; before the install. For Go, source change builds take 1.1 seconds with manifest first versus 5.7 seconds with copy first, about a 5x difference. For Python with numpy and pandas and scipy, it is 0.9 seconds versus 22.7 seconds, a 24x difference. Node with express shows 0.8 seconds versus 2.6 seconds, about 3x. Rust with axum shows 2.1 seconds versus 10.3 seconds, about 5x. Java with Spring Boot shows 3.2 seconds versus 15.9 seconds, about 5x. The gap is exactly the cost of your dependency step. Cheap npm ci gives 3x, Python native wheels give 24x.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the pattern that works. Start with your base image and install system level dependencies. These almost never change, so this layer gets cached forever. Then copy only your dependency manifest files like package.json, requirements.txt, Cargo.toml, or go.mod. Install your dependencies based on those files. This layer only rebuilds when your dependencies change, not when your code changes. Finally, copy your application code and build it. This layer rebuilds on every code change, but by this point all the expensive dependency installation is already cached.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; node:20-slim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; System deps (rarely change)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt-get update &amp;amp;&amp;amp; apt-get install -y --no-install-recommends \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ca-certificates \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Dependency manifest (changes when deps change)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; package.json package-lock.json .&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; npm ci --only=production&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Application code (changes frequently)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; npm run build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The .dockerignore file is criminally underused. Without it, &lt;code&gt;COPY . .&lt;&#x2F;code&gt; copies everything in your build context including node_modules, .git, build artifacts, and whatever else is lying around. This makes the COPY layer huge and slow, and it can invalidate your cache when files change that have nothing to do with your build.&lt;&#x2F;p&gt;
&lt;p&gt;The syntax is similar to .gitignore. For a Node.js project, a good .dockerignore might look like this.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node_modules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;dist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.github&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.gitignore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Dockerfile*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;README.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.editorconfig&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*.log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.env*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This excludes files that are recreated as part of your Dockerfile, like node_modules which are installed via npm ci. It also excludes unnecessary folders like .git and dist which will be regenerated by the build. The README and editor config have nothing to do with your application runtime. With this small change, a COPY layer that was 134MB can drop to under 150KB.&lt;&#x2F;p&gt;
&lt;p&gt;The .dockerignore also prevents cache invalidation from irrelevant changes. If you edit your README, that should not trigger a rebuild of your entire application. Without a .dockerignore, it will. With one, Docker never even sees the README change.&lt;&#x2F;p&gt;
&lt;p&gt;Multi-stage builds are essential for keeping your final image small. The idea is to use one stage for building your application with all the build tools and dependencies, then copy only the built artifacts into a minimal runtime stage. Your final image does not need gcc, make, or your entire node_modules. It just needs the compiled output and runtime dependencies.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; rust:1.75 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; debian:bookworm-slim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;app&#x2F;target&#x2F;release&#x2F;myapp &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CMD&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;myapp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The builder stage can be gigabytes with all the Rust toolchain and intermediate compilation artifacts. The final stage is just your binary and a minimal Debian base, often under 100MB. This also has security benefits since your production image has a much smaller attack surface without build tools installed.&lt;&#x2F;p&gt;
&lt;p&gt;For compiled languages like Go or Rust, bind mounts offer another optimization. You only need the compiled binary in your final image, not all of the source code. A bind mount temporarily gives the builder access to the source code to compile the binary, without including all those source files in a layer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=bind,target=. go build -o &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of a COPY instruction followed by a RUN, you mount the target directory with your source code directly to the RUN instruction. The source files are available during compilation but never become part of any layer. This avoids adding a large unnecessary layer to your image and can reduce cache invalidation from source code changes.&lt;&#x2F;p&gt;
&lt;p&gt;The cache invalidation behavior for bind mounts is different from regular RUN instructions. For a regular RUN, the builder only checks if the instruction string changed. For a RUN with a bind mount, the builder calculates a cache checksum from the metadata of the mounted files, just like it does for COPY and ADD. If any file changes, the builder invalidates the cache at that step. This makes bind mounts more predictable than regular RUN instructions that fetch external resources.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;COPY --link&lt;&#x2F;code&gt; flag is a newer optimization that can prevent cascading cache invalidation. Normally when you copy files into a layer, that layer depends on all the layers below it. If any of those layers change, your COPY layer must be rebuilt even if the files you are copying have not changed. With &lt;code&gt;--link&lt;&#x2F;code&gt;, BuildKit uses a MergeOp that efficiently merges filesystems without creating interdependencies. The copied files become their own independent layer that can be reused even when the base layers change. Netflix reported builds going from over an hour to three minutes after adopting this pattern for their large monorepo builds.&lt;&#x2F;p&gt;
&lt;p&gt;When your images start getting large and you are not sure why, the open source tool &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;wagoodman&#x2F;dive&quot;&gt;dive&lt;&#x2F;a&gt; is invaluable for analyzing what is inside them. It shows you each layer of an image, including the layer size and what files are inside. You can see what files were added, removed, or modified between layers. This makes it easy to spot problems like copying in node_modules before running npm install, or forgetting to clean up apt caches.&lt;&#x2F;p&gt;
&lt;p&gt;Dive also has a CI mode that can fail builds when images exceed efficiency thresholds. You enable it by setting &lt;code&gt;CI=true&lt;&#x2F;code&gt; or passing the &lt;code&gt;--ci&lt;&#x2F;code&gt; flag. It calculates three metrics. The efficiency score measures how much of the image is actually used versus wasted on duplicate or unnecessary files. The wasted bytes metric counts the absolute size of inefficient layers. The user wasted percent measures wasted space relative to what you added on top of the base image.&lt;&#x2F;p&gt;
&lt;p&gt;You configure thresholds in a &lt;code&gt;.dive-ci&lt;&#x2F;code&gt; file at the root of your project.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ules&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;owestEfficiency&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.95&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ighestWastedBytes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ighestUserWastedPercent&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This configuration fails the build if efficiency drops below 95 percent, if wasted space exceeds 20MB, or if more than 10 percent of your added bytes are wasted. When a threshold is violated, dive returns a non-zero exit code and prints a clear report showing which rules failed and why.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; A&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nalyze image efficiency&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;I=true dive myapp:${{ github.sha }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output in CI looks something like this when things go wrong. It shows the calculated metrics and which rules passed or failed, making it easy to understand what needs fixing.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;efficiency: 71.8643 %&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wastedBytes: 28743992 bytes (29 MB)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;userWastedPercent: 63.0335 %&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Results:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FAIL: highestUserWastedPercent: too many bytes wasted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  FAIL: lowestEfficiency: image efficiency is too low&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Result:FAIL [Total:3] [Passed:0] [Failed:2] [Skipped:1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The best practice is to start with lenient thresholds and tighten them over time. Begin with 90 percent efficiency and gradually increase as you optimize your Dockerfiles. This prevents the CI gate from becoming a blocker while still catching regressions.&lt;&#x2F;p&gt;
&lt;p&gt;A common mistake is failing to clear out the apt cache after installing packages. While the packages themselves are necessary for your image to build and run, the intermediate tarballs and package lists are not. The apt update step alone can add 20MB to your image. The traditional fix is to combine the update, install, and cleanup into a single RUN command so the cache files never make it into a layer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt-get update &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apt-get install -y --no-install-recommends build-essential &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apt-get clean &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you run the cleanup in a separate layer, the files are still in the earlier layers. Docker layers are immutable, so deleting files in a later layer just adds whiteout markers that hide them. The bytes are still there.&lt;&#x2F;p&gt;
&lt;p&gt;There is a better approach with BuildKit cache mounts. Instead of cleaning up the apt cache, you can mount it as a cache that persists across builds but never enters the image. This gives you the best of both worlds. Small images because the cache is not in any layer, and fast rebuilds because the downloaded packages are reused.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; rm -f &#x2F;etc&#x2F;apt&#x2F;apt.conf.d&#x2F;docker-clean &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Binary::apt::APT::Keep-Downloaded-Packages &amp;quot;true&amp;quot;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt; &#x2F;etc&#x2F;apt&#x2F;apt.conf.d&#x2F;keep-cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=cache,target=&#x2F;var&#x2F;cache&#x2F;apt,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,target=&#x2F;var&#x2F;lib&#x2F;apt,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apt-get update &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    apt-get install -y --no-install-recommends build-essential&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first RUN disables the automatic cleanup that official Docker images include. Without this, apt wipes the cache after every install, defeating the purpose of the cache mount. The second RUN mounts both &lt;code&gt;&#x2F;var&#x2F;cache&#x2F;apt&lt;&#x2F;code&gt; for the downloaded deb files and &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;apt&lt;&#x2F;code&gt; for the package state and lists. The &lt;code&gt;sharing=locked&lt;&#x2F;code&gt; is important because apt requires exclusive access to its cache files. Without it, parallel builds will fail with lock errors.&lt;&#x2F;p&gt;
&lt;p&gt;The performance difference is significant. A rebuild that takes 120 seconds without cache mounts can drop to 15 seconds with them, because you are not re-downloading packages that are already cached. The tradeoff is that cache mounts are local to the builder host. In CI environments with ephemeral runners, you need a strategy to persist the cache across jobs, either by pushing to a registry cache or using something like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;reproducible-containers&#x2F;buildkit-cache-dance&quot;&gt;buildkit-cache-dance&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Choosing the right base image can have a dramatic impact on size. The full node:20 image is over a gigabyte. The node:20-slim variant is about 75 percent smaller because it strips out documentation and build tools. The node:20-alpine variant is even smaller, about 85 percent smaller than the full image, because Alpine Linux uses musl libc instead of glibc and has a much smaller base system.&lt;&#x2F;p&gt;
&lt;p&gt;But Alpine comes with real tradeoffs that bite people in production. The musl libc that Alpine uses has subtle differences from glibc that can cause unexpected behavior. DNS resolution is the classic gotcha. Until Alpine 3.18, musl only supported DNS over UDP with a 512 byte limit. Large DNS responses, which are common in Kubernetes environments with many services, would fail silently. Even now, musl does not use the search domains from &lt;code&gt;&#x2F;etc&#x2F;resolv.conf&lt;&#x2F;code&gt;, so if you start Docker with &lt;code&gt;--dns-search=service.consul&lt;&#x2F;code&gt;, resolving short names will not work the way you expect.&lt;&#x2F;p&gt;
&lt;p&gt;Thread stack size is another difference that causes crashes. Musl defaults to 128KB stacks while glibc defaults to 2 to 10MB. Applications that assume larger stacks crash with segmentation faults before hitting language level recursion limits. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;python&#x2F;cpython&#x2F;issues&#x2F;76488&quot;&gt;Python had a bug&lt;&#x2F;a&gt; where recursive functions would segfault on Alpine before reaching the configured recursion limit. The fix was to explicitly set a 1MB stack size when running on musl.&lt;&#x2F;p&gt;
&lt;p&gt;Performance can also suffer. Musl uses a single lock malloc implementation while glibc uses multiple arenas to avoid contention. Multi-threaded applications can see 4x slower performance on musl due to malloc lock contention. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Project-OSRM&#x2F;osrm-backend&#x2F;pull&#x2F;7606&quot;&gt;OSRM project&lt;&#x2F;a&gt; switched from Alpine to Debian after discovering their planet graph builds took 11 hours on Alpine versus 4 hours on Debian.&lt;&#x2F;p&gt;
&lt;p&gt;Python on Alpine is particularly painful. There are no pre-built binary wheels for musl, so every C extension like numpy, pandas, or psycopg2 must compile from source. What takes seconds on Debian can take minutes on Alpine. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apache&#x2F;pulsar&#x2F;pull&#x2F;23366&quot;&gt;Apache Pulsar project&lt;&#x2F;a&gt; switched away from Alpine after experiencing JVM crashes from mixed musl and glibc library interactions.&lt;&#x2F;p&gt;
&lt;p&gt;Alpine also lacks debugging tools by default. There is no strace, gdb, or valgrind in the base image. You can install them, but valgrind has known compatibility issues with musl that can produce incorrect results.&lt;&#x2F;p&gt;
&lt;p&gt;The safe use cases for Alpine are Go binaries compiled with &lt;code&gt;CGO_ENABLED=0&lt;&#x2F;code&gt;, Rust binaries compiled for the musl target, and simple shell scripts. For Python, Node.js with native modules, Java, or anything that relies on glibc specific behavior, stick with Debian slim or distroless images.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond dive, there are several other Docker tools worth knowing about. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hadolint&#x2F;hadolint&quot;&gt;Hadolint&lt;&#x2F;a&gt; is a Dockerfile linter that catches best practice violations before they become problems. It highlights formatting issues, improper use of instructions, and patterns that lead to bloated or insecure images. Running hadolint in CI catches mistakes early.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; L&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;int Dockerfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;adolint Dockerfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;anchore&#x2F;grype&quot;&gt;Grype&lt;&#x2F;a&gt; scans images for security vulnerabilities by analyzing the packages and dependencies inside them. A common CI pattern is to fail builds if any High or Critical vulnerabilities are found. This shifts security left, catching issues before they reach production.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;can for vulnerabilities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rype myapp:latest --fail-on high&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For very large images, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containerd&#x2F;stargz-snapshotter&quot;&gt;eStargz&lt;&#x2F;a&gt; enables lazy loading of image layers. Instead of downloading the entire image before starting a container, containerd only pulls the parts that are actually accessed. This can dramatically speed up container startup times for images containing large model files or datasets. The tradeoff is more complexity in the image format and runtime, but for images measured in gigabytes, the startup time improvement is worth it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;containers.dev&#x2F;&quot;&gt;Dev Containers&lt;&#x2F;a&gt; let you develop inside a container with the same environment as your CI. VS Code mounts your local files into the container and runs extensions inside it. Every developer gets the exact same dependencies and tools. If your code works in the Dev Container, it will work in CI, because they are running the same thing. This eliminates the “works on my machine” problem at its root.&lt;&#x2F;p&gt;
&lt;p&gt;For a Node.js application, combining all these techniques can reduce an image from 700MB to under 100MB. That is a 7x reduction in size, which means faster pulls, faster deploys, and less storage cost. It also means a smaller attack surface since there are fewer binaries and packages that could have vulnerabilities.&lt;&#x2F;p&gt;
&lt;p&gt;One thing that trips people up is that Docker cannot cache RUN commands that have side effects outside the container. If your build downloads something from the internet, Docker has no way to know if the remote content changed. It will either always cache the layer or never cache it depending on whether the instruction text changed. This is why pinning versions in your Dockerfile is important. &lt;code&gt;RUN apt-get install -y curl&lt;&#x2F;code&gt; might install different versions on different days, but &lt;code&gt;RUN apt-get install -y curl=7.88.1-10+deb12u5&lt;&#x2F;code&gt; is deterministic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-filesystem-underneath-docker-matters&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-filesystem-underneath-docker-matters&quot; aria-label=&quot;Anchor link for: the-filesystem-underneath-docker-matters&quot;&gt;The filesystem underneath Docker matters&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Docker uses storage drivers to manage image layers and the writable layer on top of running containers. The default on most Linux systems is overlay2, which is a union filesystem that layers a writable upperdir on top of read-only lowerdirs representing your image layers. For 95 percent of use cases, overlay2 is the right choice. It is stable, broadly compatible, and performs well for typical workloads. But understanding how it works explains some CI performance mysteries.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest performance cost of overlay2 is copy-on-write. When a container modifies a file that exists in an image layer, overlay2 cannot write to the read-only layer. Instead it performs a copy-up operation, copying the entire file from the lowerdir to the upperdir before applying the write. This happens even if you are only changing one byte of a 500MB file. The entire file gets copied first. Subsequent writes to the same file are fast because it now exists in the writable layer, but that initial copy-up can add noticeable latency.&lt;&#x2F;p&gt;
&lt;p&gt;This is why databases inside containers without volumes are catastrophically slow on first write. A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opslog.dev&#x2F;blog&#x2F;overlayfs-deep-dive&quot;&gt;deep dive into OverlayFS performance&lt;&#x2F;a&gt; showed that writing to a new file bypasses copy-up entirely and runs at full disk speed, while writing to an existing file from the image layer incurs the copy-up penalty proportional to file size. The rule is simple. Volumes bypass OverlayFS entirely and go directly to the host filesystem at full speed. Use them for anything write-heavy.&lt;&#x2F;p&gt;
&lt;p&gt;The filesystem underneath overlay2 also matters. The choice between ext4 and XFS has real implications for CI environments with high container churn. Ext4 reserves a fixed number of inodes at format time. Each file in every Docker layer needs its own inode. Running out of inodes can prevent Docker from creating files even when you have plenty of disk space. The error message says no space left on device but &lt;code&gt;df -h&lt;&#x2F;code&gt; shows available blocks. You need to check &lt;code&gt;df -i&lt;&#x2F;code&gt; to see inode usage.&lt;&#x2F;p&gt;
&lt;p&gt;XFS handles this better because it allocates inodes dynamically from free space. Inode exhaustion before block exhaustion is practically impossible under normal Docker workloads. XFS also handles concurrent writes more efficiently and has better metadata performance. If you are provisioning CI runners, format the Docker data volume as XFS. The one requirement is that XFS must be formatted with &lt;code&gt;ftype=1&lt;&#x2F;code&gt; to support the d_type feature that overlay2 needs.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mkfs.xfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ftype=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;dev&#x2F;your-device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cr0x.net&#x2F;en&#x2F;docker-overlay2-slow-writes&#x2F;&quot;&gt;platform team case study&lt;&#x2F;a&gt; illustrates what happens when you ignore these dynamics. They saw slow build times in CI and decided to cache package directories inside the container filesystem, thinking it would avoid external IO overhead. It worked briefly. Then disk usage ballooned under &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;docker&#x2F;overlay2&lt;&#x2F;code&gt;. The host was not out of bytes but it was bleeding inodes. Cleanup jobs started taking longer. New builds became slower because every container started with a fat writable layer and a lot of directory churn. The fix was moving caches to a dedicated volume and managing it intentionally with caps and ownership. Build output became predictable again.&lt;&#x2F;p&gt;
&lt;p&gt;The other storage drivers exist for specific use cases. Btrfs and ZFS operate at the block level rather than the file level, which means they do not have the whole-file copy-up penalty. A write to a large file only copies the affected blocks. This sounds better for write-heavy workloads, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;users.cs.fiu.edu&#x2F;~raju&#x2F;WWW&#x2F;publications&#x2F;springer_jcc_2019&#x2F;paper.pdf&quot;&gt;academic research&lt;&#x2F;a&gt; found that under realistic workloads like kernel compilation and system upgrades, overlay2 and the older AUFS consistently outperformed btrfs and ZFS. The block-level drivers showed higher variance and worse performance as concurrency increased. The researchers speculated that btrfs and ZFS benefit less from the Linux page cache during mixed read-write workloads.&lt;&#x2F;p&gt;
&lt;p&gt;ZFS in particular can be painfully slow for Docker builds. One &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.chlc.cc&#x2F;p&#x2F;docker-and-zfs-a-tough-pair&#x2F;&quot;&gt;detailed investigation&lt;&#x2F;a&gt; found that creating image layers on the ZFS storage driver took minutes for operations that completed in fractions of a second on overlay2. The workaround was to create a ZFS volume, format it as ext4, and run overlay2 on top of that. Even with the extra filesystem layer, performance was dramatically better than the native ZFS driver.&lt;&#x2F;p&gt;
&lt;p&gt;For CI specifically, the performance differences between storage drivers are usually small, on the order of 5 to 10 percent for typical workloads. Container startup is fastest on overlay2 at around 50ms compared to 80 to 90ms for btrfs and ZFS. Image pulls with many layers favor overlay2 because the ZFS driver creates a dataset per layer, which involves many small operations. Container deletion is faster on btrfs and ZFS because destroying a subvolume or dataset is faster than recursively deleting directories.&lt;&#x2F;p&gt;
&lt;p&gt;The practical advice is to stick with overlay2 unless you have a specific reason to change. Use XFS as the backing filesystem if you control the runner provisioning. Move write-heavy paths to volumes. Clean up regularly with &lt;code&gt;docker system prune&lt;&#x2F;code&gt; and &lt;code&gt;docker builder prune&lt;&#x2F;code&gt;. Monitor inode usage, not just disk space. These basics prevent most of the mysterious slowdowns that teams encounter as their CI usage scales.&lt;&#x2F;p&gt;
&lt;p&gt;One subtle issue that can bite you in GitHub Actions is storage driver compatibility. GitHub periodically updates their runner images, and sometimes the Docker daemon configuration changes. The cross-rs project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cross-rs&#x2F;cross&#x2F;discussions&#x2F;1751&quot;&gt;ran into this&lt;&#x2F;a&gt; when GitHub runners switched from overlay2 to a newer overlayfs driver name. Their tooling expected the overlay2 driver name and broke when it encountered overlayfs. The fix was to force the daemon back to overlay2 in the workflow.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; F&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ix Docker storage driver&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;#39;{&amp;quot;storage-driver&amp;quot;: &amp;quot;overlay2&amp;quot;}&amp;#39; | sudo tee &#x2F;etc&#x2F;docker&#x2F;daemon.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    sudo systemctl restart docker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works because the kernel still supports both drivers. It is just that Docker defaults to the newer name now. If your workflows interact with Docker internals or use tools that make assumptions about the storage driver, you might need similar workarounds when runner images update.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-arm-situation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-arm-situation&quot; aria-label=&quot;Anchor link for: the-arm-situation&quot;&gt;The Arm situation&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Apple releasing M1 Macs in 2020 set off a chain reaction that is still playing out. Suddenly a huge portion of developers were running Arm processors on their laptops while most servers were still Intel. AWS had been pushing Graviton instances for years with promises of better price performance, but adoption was slow because building for Arm was a pain. Now everyone had a reason to care.&lt;&#x2F;p&gt;
&lt;p&gt;The naive approach to multi-platform builds is to use QEMU emulation. Docker Desktop does this automatically when you try to build an amd64 image on an Arm Mac or vice versa. It works, but it is painfully slow. Emulation can be 10 to 20 times slower than native execution depending on the workload. A build that takes 2 minutes natively might take 30 minutes under emulation. For CI pipelines that run on every commit, this is not acceptable.&lt;&#x2F;p&gt;
&lt;p&gt;The proper solution is to build natively on each architecture. This means having both Arm and Intel build machines and running the appropriate parts of your build on each. Docker buildx supports this through the &lt;code&gt;--platform&lt;&#x2F;code&gt; flag and can coordinate builds across multiple builder instances. You end up with a multi-architecture manifest that points to the appropriate image for each platform, and Docker automatically pulls the right one based on the host architecture.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild and push&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&#x2F;build-push-action@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;latforms&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;inux&#x2F;amd64,linux&#x2F;arm64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ags&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yapp:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The catch is that GitHub Actions hosted runners are all amd64. If you want native Arm builds, you need either self-hosted Arm runners or a third-party service that provides them. Some services maintain pools of both Intel and Arm machines specifically optimized for Docker builds, with persistent caches and fast networking to registries. The economics work out if your builds are slow enough that the time savings justify the cost.&lt;&#x2F;p&gt;
&lt;p&gt;Cross-compilation is another option for some languages. Go is famously good at this. You can build a linux&#x2F;arm64 binary on an amd64 machine without emulation because the Go compiler just targets a different architecture. Rust can do this too with the right target installed. The Dockerfile pattern is to do the cross-compilation in a builder stage on your native architecture, then copy the resulting binary into a minimal base image for the target architecture.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; --platform=$BUILDPLATFORM rust:1.75 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ARG&lt;&#x2F;span&gt;&lt;span&gt; TARGETPLATFORM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; case &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$TARGETPLATFORM&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; in \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;linux&#x2F;amd64&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) echo &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;x86_64-unknown-linux-gnu&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt; &#x2F;target.txt ;; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;linux&#x2F;arm64&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) echo &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;aarch64-unknown-linux-gnu&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt; &#x2F;target.txt ;; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    esac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; rustup target add $(cat &#x2F;target.txt)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo build --release --target $(cat &#x2F;target.txt)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; debian:bookworm-slim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;app&#x2F;target&#x2F;*&#x2F;release&#x2F;myapp &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;--platform=$BUILDPLATFORM&lt;&#x2F;code&gt; on the builder stage means it runs on the native architecture of the build machine. The &lt;code&gt;TARGETPLATFORM&lt;&#x2F;code&gt; argument tells you what architecture you are building for. This way you get native compilation speed while still producing binaries for multiple architectures.&lt;&#x2F;p&gt;
&lt;p&gt;For interpreted languages like Python or Node, multi-platform is simpler because there is no compilation step for your code. The complexity is in native dependencies. If your Python package has C extensions, those need to be compiled for each architecture. The base images handle this for the standard library, but third-party packages with native code can be tricky.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-happens-when-you-push-to-github&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-happens-when-you-push-to-github&quot; aria-label=&quot;Anchor link for: what-happens-when-you-push-to-github&quot;&gt;What happens when you push to GitHub?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Understanding what GitHub Actions actually does when you trigger a workflow helps explain why things are slow and what you can do about it. When you push a commit, GitHub receives the webhook, evaluates which workflows should run based on your trigger conditions, and queues jobs for execution. Each job gets assigned to a runner, which is a virtual machine that will execute your workflow steps.&lt;&#x2F;p&gt;
&lt;p&gt;For GitHub-hosted runners, this means spinning up a fresh VM from a base image. The VM has a bunch of common tools preinstalled like Docker, Node, Python, and various build tools, but it starts with no knowledge of your project. Every workflow run begins from scratch. Your repository gets cloned, your dependencies get installed, your caches get downloaded, and only then does your actual work begin. This cold start overhead is why even simple workflows take a minute or two before they do anything useful.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;actions&#x2F;runner-images&quot;&gt;runner images&lt;&#x2F;a&gt; are maintained by GitHub and updated regularly. They include a lot of preinstalled software to reduce setup time, but this also means they are large. The ubuntu-latest image is over 20GB. Most of that is stuff you will never use, but it is there just in case. The tradeoff is that common tools are available immediately without installation, but the VM takes longer to provision.&lt;&#x2F;p&gt;
&lt;p&gt;Queue time is another factor that is often overlooked. When you trigger a workflow, your job goes into a queue and waits for an available runner. During busy periods or if you are on a free tier with limited concurrency, this wait can be significant. I have seen queue times of 5 to 10 minutes during peak hours. There is not much you can do about this except pay for more concurrent runners or use self-hosted runners.&lt;&#x2F;p&gt;
&lt;p&gt;Self-hosted runners change the equation significantly. Instead of GitHub provisioning a fresh VM for each job, you run the runner software on your own infrastructure. The runner can be persistent, meaning it keeps state between jobs. Your Docker layer cache persists. Your dependency caches persist. The runner is already warm and ready to go. The downside is that you are responsible for maintaining the infrastructure, handling security, and ensuring the runner is available when needed.&lt;&#x2F;p&gt;
&lt;p&gt;The security concerns with self-hosted runners are real. Runners accumulate credentials on disk over time. Cloud configs, Kubernetes secrets, Docker configs, SSH keys, shell histories, and infrastructure state files all pile up. If an attacker gets code execution on your runner, they can walk the filesystem and harvest credentials. Attackers can also read secrets from runner process memory by scraping &lt;code&gt;&#x2F;proc&lt;&#x2F;code&gt;. The recommendation is to use ephemeral runners that destroy the environment after every job, but that means you lose your warm caches.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a persistence attack where malicious code sets the &lt;code&gt;RUNNER_TRACKING_ID&lt;&#x2F;code&gt; environment variable to zero, which prevents the runner from terminating orphaned processes after the workflow finishes. Spawned processes can persist indefinitely, waiting for the next job to steal credentials from.&lt;&#x2F;p&gt;
&lt;p&gt;Starting March 2026, GitHub charges $0.002 per minute for self-hosted runners on private repositories. This is still 60 to 80 percent cheaper than GitHub-hosted runners at scale, but it is a new cost to factor in. Runners that miss software updates for more than 30 days stop receiving jobs, which forces continuous image rebuilds and Helm upgrades if you are using the Actions Runner Controller on Kubernetes.&lt;&#x2F;p&gt;
&lt;p&gt;One trick that works well for self-hosted runners is using a RAM disk for the working directory. Disk I&#x2F;O is often the bottleneck for build operations, especially for languages like Rust that generate huge amounts of intermediate files. By mounting a tmpfs at the runner’s work directory, all those file operations happen in memory instead of hitting the disk. This can cut Rust CI times in half or more, which sounds too good to be true until you realize how much time rustc spends waiting on disk.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uild&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;elf-hosted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;etup RAM disk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          sudo mkdir -p &#x2F;mnt&#x2F;ramdisk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          sudo mount -t tmpfs -o size=16G tmpfs &#x2F;mnt&#x2F;ramdisk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;mnt&#x2F;ramdisk&#x2F;repo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The ephemeral nature of GitHub-hosted runners is both a blessing and a curse. It is a blessing because you get a clean environment every time, no accumulated cruft, no state leaking between builds, no security concerns about previous jobs leaving sensitive data behind. It is a curse because you pay the cold start cost every single time. Third-party runner services offer faster runners with better caching, essentially giving you the benefits of self-hosted runners without the operational overhead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-caching-game&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-caching-game&quot; aria-label=&quot;Anchor link for: the-caching-game&quot;&gt;The caching game&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Caching is where the real performance gains live, but it is also where things get confusing. There are multiple layers of caching that can interact in unexpected ways, and getting them all working together requires understanding what each one does.&lt;&#x2F;p&gt;
&lt;p&gt;The GitHub Actions cache is the most commonly used. The &lt;code&gt;actions&#x2F;cache&lt;&#x2F;code&gt; action lets you save and restore arbitrary directories between workflow runs. The typical use case is caching your dependency directories like node_modules, the pip cache, or the cargo registry. You specify a key that identifies the cache, and if a cache with that key exists, it gets restored at the start of your job.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;cache@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;.cargo&#x2F;registry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo-${{ hashFiles(&amp;#39;**&#x2F;Cargo.lock&amp;#39;) }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;estore-keys&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      cargo-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The key design is crucial. You want the cache to hit when your dependencies have not changed, but miss when they have. Using a hash of your lockfile is the standard pattern. The &lt;code&gt;restore-keys&lt;&#x2F;code&gt; provide fallback options if an exact match is not found. This way you can still get a partial cache hit even if your dependencies changed slightly.&lt;&#x2F;p&gt;
&lt;p&gt;The cache backend was completely rewritten in early 2025. GitHub deprecated the legacy cache service and switched to a new Twirp based service using the Azure Blob Storage SDK. The new service rolled out in February 2025 and the legacy service was sunset on the same date. If you are using old versions of the cache action, your workflows will fail. You need to be on v3.4.0 or v4.2.0 or newer.&lt;&#x2F;p&gt;
&lt;p&gt;The 10GB cache limit per repository is a real constraint for larger projects. GitHub automatically evicts old caches when you hit the limit, but this can cause cache misses at inconvenient times. Caches that are not accessed within the last week also get evicted. If you have multiple workflows or matrix builds, they all share this limit. You need to be strategic about what you cache and how you key it.&lt;&#x2F;p&gt;
&lt;p&gt;There is a subtle gotcha with cache versioning. The cache version is a hash generated from the compression tool used and the paths being cached. This means a cache created on a Windows runner cannot be restored on an Ubuntu runner because they use different compression. Even on the same OS, if you change the paths you are caching, you get a different version and the old cache becomes inaccessible. The list caches API can help troubleshoot cache misses due to version mismatches.&lt;&#x2F;p&gt;
&lt;p&gt;Another gotcha is that caches are immutable. You cannot update an existing cache. If you want to change the contents, you have to create a new key. This is why lockfile hashes work well as cache keys. When your dependencies change, the lockfile changes, which changes the hash, which creates a new cache key.&lt;&#x2F;p&gt;
&lt;p&gt;There are also rate limits to be aware of. Uploads are limited to 200 per minute per repository. Downloads are limited to 1500 per minute per repository. If you exceed these limits, you get a Retry-After header. This usually only matters for large matrix builds or monorepos with many parallel jobs.&lt;&#x2F;p&gt;
&lt;p&gt;Security is worth thinking about too. Anyone with PR access can read cache contents, so never cache secrets or sensitive data. Fork PRs have read only access to the default branch cache, which prevents cache poisoning from untrusted code. But caches are not signed or verified, so a compromised workflow could theoretically write malicious content to the cache that gets restored by other workflows.&lt;&#x2F;p&gt;
&lt;p&gt;For teams that need more than 10GB, there are alternatives. Some third-party runner services offer sticky disks that mount NVMe storage directly into your runner. The performance difference is dramatic. Restoring a 6GB cache from GitHub Actions takes about 66 seconds at 90 MB&#x2F;s. The same cache from a sticky disk takes 3 seconds because there is no network transfer at all. The disk is just mounted. One team reported their Node setup time dropped from 47 seconds to 6 seconds after switching to sticky disks.&lt;&#x2F;p&gt;
&lt;p&gt;The reason NVMe is so much faster than network based caching comes down to physics. AWS EBS volumes, which is what most cloud CI uses, have a typical write throughput of around 140 MB&#x2F;s. NVMe instance storage can hit 900 MB&#x2F;s or more, a 6x improvement in write throughput alone. Read performance is similarly dramatic. When your build is constantly reading and writing intermediate files, this difference compounds.&lt;&#x2F;p&gt;
&lt;p&gt;Some providers run distributed storage systems like Ceph to persist Docker layer cache during a build and then reattach that cache across builds. Ceph offers the ability to persist cache across fast NVMe local storage while maintaining minimal network latency by keeping the volume and builder in the same availability zone. The cache is not on the ephemeral instance itself, so it survives instance termination, but it is close enough that access is nearly as fast as local storage.&lt;&#x2F;p&gt;
&lt;p&gt;The architecture typically involves a standby pool of warm machines that have been configured to run Docker image builds. Instead of launching a new on demand instance for every build, which can take 40 seconds to 5 minutes, the service maintains a fleet of optimized builders in a stopped state. Transitioning from stopped to running only takes 2 to 3 seconds, as opposed to the full lifecycle of launching a new instance. This additional 2 to 3 seconds is trivial compared to the massive time savings from caching between builds.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a recognition that if you just built an image, you are likely to build another one soon after. Services optimize for this by keeping your machine active for a window after every build, typically around 2 minutes. During development when you are constantly adjusting your code and running new builds, your build starts immediately as the machine stays online for that additional time window.&lt;&#x2F;p&gt;
&lt;p&gt;The security model matters here too. Because a Docker build needs root permissions, the build isolation level is typically drawn at the instance level. Your build runs in your own instance with no other projects sharing that machine. When your build is finished, the machine is destroyed and never reused again. This avoids noisy neighbor builds where another customer’s build could hog compute resources, starving other builds. Single tenant systems have this explicit security benefit of isolating at the level of the instance rather than using a shared Kubernetes cluster.&lt;&#x2F;p&gt;
&lt;p&gt;Some providers have reverse engineered the GitHub Actions cache internals to make it faster without requiring any code changes. The approach involves intercepting cache requests at the network level and routing them to a colocated cache instead of GitHub’s servers. Every VM request still appears to go to the original destination, but under the hood it gets redirected within the network stack. The result is cache speeds up to 10 times faster. One benchmark showed a 114 MB cache downloading at 327 MB&#x2F;s instead of 50 MB&#x2F;s, completing in a single log line instead of multiple progress updates.&lt;&#x2F;p&gt;
&lt;p&gt;The catch is that sticky disks require running on specific infrastructure. They are not available on GitHub-hosted runners. You need either self-hosted runners or a third-party service that supports them. And any action that interacts with the host system might break when running in a container, which is a common pattern for reproducible builds.&lt;&#x2F;p&gt;
&lt;p&gt;Docker layer caching in GitHub Actions is a separate beast. The &lt;code&gt;docker&#x2F;build-push-action&lt;&#x2F;code&gt; supports several cache backends through BuildKit. The simplest is inline caching, where cache metadata is embedded in the image itself. This works but has limitations. The more powerful option is using the GitHub Actions cache as a BuildKit cache backend.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&#x2F;build-push-action@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ache-from&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ype=gha&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ache-to&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ype=gha,mode=max&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;mode=max&lt;&#x2F;code&gt; setting is important. By default, BuildKit only caches the final image layers. With &lt;code&gt;mode=max&lt;&#x2F;code&gt;, it caches all intermediate layers from all stages, which is what you want for build performance. The downside is that this uses more of your cache quota.&lt;&#x2F;p&gt;
&lt;p&gt;Registry-based caching is another option where you push cache layers to a container registry. This can be useful if you are hitting the GitHub Actions cache limit or if you want to share cache between different CI systems. The tradeoff is that pushing and pulling from a registry adds network latency.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&#x2F;build-push-action@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ache-from&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ype=registry,ref=ghcr.io&#x2F;myorg&#x2F;myapp:cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ache-to&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ype=registry,ref=ghcr.io&#x2F;myorg&#x2F;myapp:cache,mode=max&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For Rust projects, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mozilla&#x2F;sccache&quot;&gt;sccache&lt;&#x2F;a&gt; is a game changer. It is a compiler cache that works like ccache but supports Rust and can use remote storage backends like S3 or GCS. Instead of caching the entire target directory, it caches individual compilation units. This means you get cache hits even when your Cargo.lock changes, as long as the individual crates have not changed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;etup sccache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ozilla-actions&#x2F;sccache-action@v0.0.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;CCACHE_GHA_ENABLED&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    R&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;USTC_WRAPPER&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ccache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The sccache GitHub Actions integration uses the GitHub Actions cache as its backend, which is convenient but shares the same 10GB limit. For larger projects, pointing sccache at a GCS bucket or S3 gives you effectively unlimited cache storage. Some teams configure sccache with a GCS bucket in read-write mode for their main CI and read-only mode for fork PRs, so external contributors still get cache hits without being able to poison the cache.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  R&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;USTC_WRAPPER&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ccache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  S&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;CCACHE_GCS_BUCKET&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y-sccache-bucket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  S&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;CCACHE_GCS_RW_MODE&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;EAD_WRITE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  C&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ARGO_INCREMENTAL&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;CARGO_INCREMENTAL: 0&lt;&#x2F;code&gt; is important because sccache cannot cache incremental builds. You trade incremental compilation for distributed caching, which is usually a good tradeoff in CI where you are starting from scratch anyway.&lt;&#x2F;p&gt;
&lt;p&gt;One thing that catches people off guard is that caches are scoped to branches. A cache created on a feature branch is not available to the main branch, though caches from the main branch are available to feature branches. This is a security measure to prevent untrusted code from poisoning the cache, but it means your first build on a new branch might be slower than expected.&lt;&#x2F;p&gt;
&lt;p&gt;The branch scoping gets even more confusing with tags. Tag triggered workflows get their own scope and cannot access branch caches at all. This is a major pain point for release workflows. You build and test on main, everything is cached and fast. Then you tag a release and suddenly the release build takes forever because it cannot access any of the caches from main. The workaround is to build release artifacts on the branch before tagging, but that adds complexity to your release process.&lt;&#x2F;p&gt;
&lt;p&gt;Pull request caches are scoped to &lt;code&gt;refs&#x2F;pull&#x2F;...&#x2F;merge&lt;&#x2F;code&gt; which means very limited reuse. Each PR gets its own cache scope, so the first build on a new PR is always slow. Fork PRs have it even worse. They get read only access to the default branch cache but cannot write new caches. This creates friction for open source projects where external contributors always have slow first builds.&lt;&#x2F;p&gt;
&lt;p&gt;Cache thrashing is another common problem. The symptom is that the cache gets saved and restored, but your install step still takes the full time. The cause is usually too many unique keys filling up the 10GB limit, which evicts useful caches. If you use the commit SHA or run ID in your cache key without restore keys, you create a unique key every commit and never get cache hits. The fix is to use stable keys based on lockfile hashes and let restore keys handle partial matches.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes you need to build without the cache entirely. Maybe you are debugging a caching issue, or you need to force Docker to fetch fresh external resources, or you are following the best practice of rebuilding images periodically to pick up security updates. The &lt;code&gt;--no-cache&lt;&#x2F;code&gt; flag tells BuildKit to ignore all cached layers and rebuild everything from scratch.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-no-cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For multi-stage builds, you might only want to invalidate the cache for specific stages. The &lt;code&gt;--no-cache-filter&lt;&#x2F;code&gt; option lets you target individual stages by name while keeping the cache for others.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-no-cache-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; builder&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myapp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This rebuilds the builder stage from scratch but still uses cached layers for other stages. It is useful when you want to force a dependency update in one stage without rebuilding your entire image.&lt;&#x2F;p&gt;
&lt;p&gt;On the cleanup side, Docker accumulates build cache over time. The &lt;code&gt;docker buildx prune&lt;&#x2F;code&gt; command clears the build cache. By default it only removes dangling layers that are not referenced by any builds. Add &lt;code&gt;--all&lt;&#x2F;code&gt; to remove all unused cache.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; prune&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-all&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also filter by age. This command removes cache older than two days.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; prune&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; until=48h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or keep a specific amount of cache and delete the rest. This keeps 10GB of the most recently used cache.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; buildx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; prune&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-keep-storage&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 10GB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Before pruning, check what is actually using disk space with &lt;code&gt;docker system df&lt;&#x2F;code&gt;. It shows usage broken down by images, containers, volumes, and build cache, along with how much is reclaimable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; system&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; df&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are individual prune commands for each resource type. &lt;code&gt;docker container prune&lt;&#x2F;code&gt; removes all stopped containers. &lt;code&gt;docker image prune&lt;&#x2F;code&gt; removes dangling images, which are images with no tags and no container association. Add &lt;code&gt;-a&lt;&#x2F;code&gt; to remove all unused images including tagged ones not associated with any container. The difference can be dramatic. You might reclaim 2.7GB with &lt;code&gt;docker image prune&lt;&#x2F;code&gt; but 22GB with &lt;code&gt;docker image prune -a&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;docker volume prune&lt;&#x2F;code&gt; removes anonymous volumes not used by containers. Add &lt;code&gt;-a&lt;&#x2F;code&gt; to include named volumes. Volumes are never cleaned up automatically because they could contain valuable data like database files or user uploads. You have to explicitly prune them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;docker network prune&lt;&#x2F;code&gt; removes unused networks, cleaning up network bridges, iptables rules, and routing tables.&lt;&#x2F;p&gt;
&lt;p&gt;The nuclear option is &lt;code&gt;docker system prune&lt;&#x2F;code&gt; which removes all unused containers, images, networks, and build cache in one command. Add &lt;code&gt;--volumes&lt;&#x2F;code&gt; to include volumes and &lt;code&gt;-a&lt;&#x2F;code&gt; to include all unused images, not just dangling ones.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; system&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; prune&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-volumes&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;af&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The builder also runs garbage collection periodically in the background. Default policies define when and how the builder cleans up unused cache or cache that exceeds size limits. For large scale builds or self-managed builders, you might need to customize these policies for more frequent collection or larger size limits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;remote-caching-is-the-next-frontier&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#remote-caching-is-the-next-frontier&quot; aria-label=&quot;Anchor link for: remote-caching-is-the-next-frontier&quot;&gt;Remote caching is the next frontier&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Local caching is great, but it has a fundamental problem. The cache is local to your machine. When you are working with a CI system, this results in a lot of duplicated work. The same task gets re-executed on each machine, by you, by your teammates, by your CI, by your PaaS, even when all of the task inputs are identical. This wastes time and resources.&lt;&#x2F;p&gt;
&lt;p&gt;Remote caching takes it to another level by making those reusable pieces of work shared across your entire team and between your local machine and CI. The idea is simple. If someone on your team already built something with the exact same inputs, why should you build it again? You should just download the result.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;survey.stackoverflow.co&#x2F;2024&#x2F;&quot;&gt;2024 Stack Overflow Survey&lt;&#x2F;a&gt; found that nearly 33 percent of respondents noted complexity of tech stack for build as a common frustration. Research on developer experience found that slow builds contribute to engineering system friction, feeling blocked or stuck, poor productivity, and interruptions. Waiting for slow builds gets in the way of focus time and frustratingly interrupts workflow. By the time you have enough signal to form a decent hypothesis about a bug, you are already cognitively cooked.&lt;&#x2F;p&gt;
&lt;p&gt;For monorepos using Turborepo, remote caching enables teams to share task results globally. CI goes from 6 minutes to 45 seconds on a warm cache. That is not a typo. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turborepo.dev&#x2F;docs&#x2F;core-concepts&#x2F;remote-caching&quot;&gt;Turborepo documentation&lt;&#x2F;a&gt; reports that remote caching can provide a 10x improvement on repeated CI runs for unchanged code. Combined with proper filtering, you can see 3 to 5x improvement for typical feature PRs.&lt;&#x2F;p&gt;
&lt;p&gt;The key insight is that builds become incremental. Instead of always having to rebuild from scratch, only the parts of your codebase that have changed are rebuilt, and only affected tests are re-run. This works because the cache is keyed on the hash of the inputs. Same inputs, same hash, same output. No need to recompute.&lt;&#x2F;p&gt;
&lt;p&gt;Latency is the enemy of remote caching. If it takes longer to download the cached result than to just rebuild it, the cache is useless. The solution is data locality. A good remote cache service is backed by a global CDN. When you run a build in Oregon, you pull your cache artifacts from a cache node closest to you. When you run inside of a CI runner, the cache routes through fast networks to pull from a node closest to your runner.&lt;&#x2F;p&gt;
&lt;p&gt;For Rust projects, there is an interesting development. Turborepo’s task cache is all or nothing for a Cargo crate. Any input change re-runs the whole cargo build. In CI with cold containers and empty target directories, that means recompiling everything on every task cache miss. But sccache can cache individual compilation units. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vercel&#x2F;turborepo&#x2F;pull&#x2F;13288&quot;&gt;Turborepo team recently added&lt;&#x2F;a&gt; experimental support for serving the remote cache as an sccache backend. The two layers compose. A task cache hit skips execution entirely. A task cache miss has its rustc invocations served from the compile cache. Their benchmarks showed 3.4x speedup with 407 out of 407 compile unit hits.&lt;&#x2F;p&gt;
&lt;p&gt;The performance gains from sccache with remote storage can be dramatic. One benchmark from the RisingWave project showed builds going from 21 minutes 40 seconds to 1 minute 52 seconds with a warm cache, an 11.5x improvement. The key is that sccache operates at the individual crate level, which is more granular than caching the entire target directory.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;urbo.json&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;futureFlags&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;experimentalCargoSccache&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is CI only by design. Local development is already served by cargo’s incremental compilation and a warm target directory. The injected &lt;code&gt;CARGO_INCREMENTAL=0&lt;&#x2F;code&gt; that sccache requires would actively degrade local builds. Since the flag is repo level configuration, engaging locally would slow down every contributor’s inner loop to speed up a case cargo already handles.&lt;&#x2F;p&gt;
&lt;p&gt;Bazel has been doing remote caching for years. A remote cache is used by a team of developers and a CI system to share build outputs. If your build is reproducible, the outputs from one machine can be safely reused on another machine. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bazel.build&#x2F;remote&#x2F;caching&quot;&gt;Bazel documentation&lt;&#x2F;a&gt; describes how to set up a server to act as the cache backend. A HTTP&#x2F;1.1 server can treat Bazel’s data as opaque bytes, so many existing servers can be used. There is also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;buchgr&#x2F;bazel-remote&quot;&gt;bazel-remote&lt;&#x2F;a&gt;, an open source remote build cache that has been successfully used in production at several companies since early 2018.&lt;&#x2F;p&gt;
&lt;p&gt;Starting with Bazel 7.4, you can use &lt;code&gt;--experimental_disk_cache_gc_max_size&lt;&#x2F;code&gt; and &lt;code&gt;--experimental_disk_cache_gc_max_age&lt;&#x2F;code&gt; to set a maximum size for the disk cache or for the age of individual cache entries. Bazel will automatically garbage collect the disk cache while idling between builds.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest mistake teams make with remote caching is not configuring outputs correctly. Without proper output configuration, the cache cannot restore builds correctly. You end up with stale artifact bugs where the cache thinks it has a hit but the restored files are wrong or incomplete. Match your actual build output directories. The cache stores and restores these on cache hit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-hidden-queue-time-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-hidden-queue-time-problem&quot; aria-label=&quot;Anchor link for: the-hidden-queue-time-problem&quot;&gt;The hidden queue time problem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When you trigger a GitHub Actions workflow, there is a delay before your job actually starts running. This queue time is often overlooked, but it can add up. For ephemeral runners, the initialization process has four key steps. Download the API schema. Get an OAuth token. Create a session. Long poll for a GitHub job.&lt;&#x2F;p&gt;
&lt;p&gt;One &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;depot.dev&#x2F;blog&#x2F;reducing-queue-time-with-cached-schemas&quot;&gt;detailed investigation&lt;&#x2F;a&gt; found that on average, the first three steps took about 3.7 seconds. That does not sound terrible, but the variance was alarming. The p99 latency reached 39 seconds, and the longest time recorded was 121 seconds. For 39 seconds, and almost two minutes in the worst case, a job is just waiting to be picked up.&lt;&#x2F;p&gt;
&lt;p&gt;The culprit was API schema downloads. The first step involves a network call to download the entire Azure DevOps API schema, a 50KB JSON document mapping UUIDs to API endpoints. The schema ends up getting downloaded three times during initialization in order to resolve API endpoint templates. For instance, the schema might map a UUID like &lt;code&gt;134e239e-2df3-4794-a6f6-24f1f19ec8dc&lt;&#x2F;code&gt; to a templated endpoint like &lt;code&gt;_apis&#x2F;{area}&#x2F;pools&#x2F;{poolId}&#x2F;{resource}&#x2F;{sessionId}&lt;&#x2F;code&gt;. The runner code then fills in values to construct the final API calls.&lt;&#x2F;p&gt;
&lt;p&gt;The Action Runner caches the API schema to disk after downloading and refreshes it every hour. But ephemeral runners start fresh for every job, so the API schema is downloaded anew, three times, for every job. Workflows with dozens of tasks are fairly common, and this repeated download causes noticeable latency.&lt;&#x2F;p&gt;
&lt;p&gt;The fix was to implement a single cached schema for all of an organization’s jobs. A simple service downloads and caches each organization’s API schema in object storage, refreshing it regularly in the background. When an ephemeral runner starts, the cached schema is placed on disk without the runner needing to wait.&lt;&#x2F;p&gt;
&lt;p&gt;The results were dramatic. By caching the API schemas, the p99 latency dropped from 39 seconds to 9 seconds. The sometimes high latency in downloading the schema is now completely avoided. The runner no longer needs to download the API schema at all on initialization.&lt;&#x2F;p&gt;
&lt;p&gt;There was an additional bottleneck in fetching OAuth tokens. Some spikes near 60 seconds were caused by connection timeouts. The fix was adding a much faster timeout and retry mechanism. These are the kinds of optimizations that are invisible to users but make a real difference in how fast your CI feels.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;third-party-actions-worth-knowing-about&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#third-party-actions-worth-knowing-about&quot; aria-label=&quot;Anchor link for: third-party-actions-worth-knowing-about&quot;&gt;Third party actions worth knowing about&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The GitHub Actions ecosystem has matured into a sophisticated toolkit where specialized solutions often outperform general purpose alternatives. An &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;depot.dev&#x2F;blog&#x2F;we-analyzed-66821-github-actions-runs&quot;&gt;analysis of 66,821 workflow runs&lt;&#x2F;a&gt; across organizations revealed some hidden gems that could transform your workflows.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dorny&#x2F;paths-filter&quot;&gt;dorny&#x2F;paths-filter&lt;&#x2F;a&gt; action is used by 11 percent of organizations. It detects which files changed in a PR and sets outputs you can use to conditionally run jobs. This is great when you want to control running individual jobs or steps only when certain file changes happen.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;orny&#x2F;paths-filter@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hanges&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ilters&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      backend:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        - &amp;#39;src&#x2F;api&#x2F;**&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      frontend:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        - &amp;#39;src&#x2F;web&#x2F;**&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un backend tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;teps.changes.outputs.backend == &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;npm run test:api&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a big improvement over workflow level filters. Jobs that do not match get skipped instantly, and you can see in the Actions UI exactly which ones ran. The changes output is a JSON array of matching filter names, which opens the door to dynamic matrix strategies. For monorepos, this can cut CI time by 60 to 80 percent for single package PRs.&lt;&#x2F;p&gt;
&lt;p&gt;Be careful though. Path filters that skip full regression suites before merge to main are a common source of green PR, broken main. Gate path filter skip on PRs, but run full suite on main pushes. That is the safe pattern.&lt;&#x2F;p&gt;
&lt;p&gt;For Python projects, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;setup-uv&quot;&gt;astral-sh&#x2F;setup-uv&lt;&#x2F;a&gt; is used by 7 percent of organizations. Installing Python dependencies can take a really long time. Astral’s uv comes to the rescue with about 6x faster installs. By default the action caches, which makes things even better.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stral-sh&#x2F;setup-uv@v6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nstall dependencies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v pip install -r requirements.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mozilla-actions&#x2F;sccache-action&quot;&gt;mozilla-actions&#x2F;sccache-action&lt;&#x2F;a&gt; is used by 6 percent of organizations. It speeds up compilation for Rust, C++, and other compiled languages by caching compilation results across CI runs.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;awalsh128&#x2F;cache-apt-pkgs-action&quot;&gt;awalsh128&#x2F;cache-apt-pkgs-action&lt;&#x2F;a&gt; is used by 2 percent of organizations. In CI, installing packages from apt can take a long time. This action caches packages, eliminating repeated package downloads and installations.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;walsh128&#x2F;cache-apt-pkgs-action@v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ackages&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ibssl-dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are caveats though. This action is based on the principle that most packages can be cached as a fileset. There are situations where this is not enough. Pre and post installation scripts need to be run from &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;dpkg&#x2F;info&#x2F;{package name}.[preinst, postinst]&lt;&#x2F;code&gt;. The Debian package database needs to be queried for scripts above. The &lt;code&gt;execute_install_scripts&lt;&#x2F;code&gt; argument can be used to attempt to execute the install scripts but they are not guaranteed to resolve the issue. If this does not solve your issue, you will need to run &lt;code&gt;apt-get install&lt;&#x2F;code&gt; as a separate step for that particular package.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nick-fields&#x2F;retry&quot;&gt;nick-fields&#x2F;retry&lt;&#x2F;a&gt; action is used by 4 percent of organizations. As much as engineers do not want it to be true, it is not uncommon for tests to be flaky. This action can automatically retry failed steps with configurable backoff. It might be controversial, but it is definitely pragmatic.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ick-fields&#x2F;retry@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imeout_minutes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ax_attempts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;npm run integration-tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also run a cleanup command before each retry, which is useful for tests that leave state behind.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ick-fields&#x2F;retry@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imeout_seconds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 15&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ax_attempts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pm run some-flaky-script-that-outputs-something&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;n_retry_command&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pm run cleanup-flaky-script-output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;marocchino&#x2F;sticky-pull-request-comment&quot;&gt;marocchino&#x2F;sticky-pull-request-comment&lt;&#x2F;a&gt; action is used by 4 percent of organizations. It updates a single comment on PRs instead of creating new ones. This is nice as it can help reviewers get context from a PR instead of digging through CI logs.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;arocchino&#x2F;sticky-pull-request-comment@v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;overage-results.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dorny&#x2F;test-reporter&quot;&gt;dorny&#x2F;test-reporter&lt;&#x2F;a&gt; action is used by 3 percent of organizations. Test failures become immediately visible in PR checks with detailed context. For me, it is pretty painful to search through go test logs for the word fail. Too many tests or logs have that as their name. This action parses test results in XML or JSON format and creates nice reports as GitHub Check Runs or job summaries. It supports .NET, Dart, Flutter, Go, Java, JavaScript, Python, PHP, Ruby, and Swift.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o test -json .&#x2F;... &amp;gt; testresults.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;est Report&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;orny&#x2F;test-reporter@v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; G&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o Tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;estresults.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eporter&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;olang-json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;taiki-e&#x2F;install-action&quot;&gt;taiki-e&#x2F;install-action&lt;&#x2F;a&gt; is used by 3 percent of organizations. It simplifies and speeds up getting the right tools into the CI environment. It installs precompiled binaries from GitHub releases with automatic caching and platform detection. The GitHub repo includes a list of all the tools it supports ready to go.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;aiki-e&#x2F;install-action@v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ool&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo-nextest,just,cargo-hack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The action verifies SHA256 checksums for downloaded files and also verifies artifact attestations or signatures if the tool publishes them. When installing without specifying a version, the tool version reflects upstream releases with a delay of one to a few days. This dependency cooldown is intended to mitigate the risk of supply chain attacks.&lt;&#x2F;p&gt;
&lt;p&gt;Worth noting that the most adopted third party action in the analysis was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pnpm&#x2F;action-setup&quot;&gt;pnpm&#x2F;action-setup&lt;&#x2F;a&gt; at 17 percent of organizations. Fast package management is clearly a priority for teams optimizing their CI. Other notable mentions include &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;codecov&#x2F;codecov-action&quot;&gt;codecov&#x2F;codecov-action&lt;&#x2F;a&gt; for coverage reporting at 7 percent, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&#x2F;rust-toolchain&quot;&gt;dtolnay&#x2F;rust-toolchain&lt;&#x2F;a&gt; for Rust setup at 6 percent, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;oven-sh&#x2F;setup-bun&quot;&gt;oven-sh&#x2F;setup-bun&lt;&#x2F;a&gt; for the Bun JavaScript runtime at 6 percent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-in-ci-is-its-own-special-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rust-in-ci-is-its-own-special-problem&quot; aria-label=&quot;Anchor link for: rust-in-ci-is-its-own-special-problem&quot;&gt;Rust in CI is its own special problem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Rust compilation is notoriously slow, and CI makes it worse. On your local machine, incremental compilation helps a lot. Change one file, and cargo only recompiles what is affected. But in CI, you typically start from scratch every time, which means full rebuilds. A medium-sized Rust project can easily take 10 to 20 minutes to compile from scratch, and larger projects can take much longer.&lt;&#x2F;p&gt;
&lt;p&gt;The fundamental issue is that Rust does a lot of work at compile time. Monomorphization, borrow checking, and optimization all take time. The compiler is also single-threaded for much of its work, so throwing more cores at it only helps to a point. And the target directory where all the intermediate artifacts live can grow to gigabytes, making it expensive to cache and restore.&lt;&#x2F;p&gt;
&lt;p&gt;The naive approach of caching the entire target directory does not work well. The target directory contains a lot of stuff that is specific to the exact compiler version, feature flags, and build profile. If any of those change, the cache is useless or worse, it can cause weird build failures. The cache also gets huge quickly, eating into your GitHub Actions cache quota.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LukeMathWalker&#x2F;cargo-chef&quot;&gt;cargo-chef&lt;&#x2F;a&gt; is a clever solution for Docker builds. It works by creating a dummy project with the same dependencies as your real project, building that first to cache all the dependency compilation, then copying in your actual source code. This way, the expensive dependency compilation layer only rebuilds when your Cargo.toml or Cargo.lock changes.&lt;&#x2F;p&gt;
&lt;p&gt;The problem cargo-chef solves is fundamental to how Docker caching works with Rust. When you run &lt;code&gt;cargo build&lt;&#x2F;code&gt; in Docker, the entire compilation is treated as a single operation. Any change to your source code invalidates the cache and forces recompilation of all dependencies. Cargo-chef separates these concerns by creating a recipe from your dependency files that only changes when dependencies change, not when source code changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; rust:1.75 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; chef&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo install cargo-chef&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; chef &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; planner&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo chef prepare --recipe-path recipe.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; chef &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=planner &#x2F;app&#x2F;recipe.json recipe.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo chef cook --release --recipe-path recipe.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; debian:bookworm-slim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;app&#x2F;target&#x2F;release&#x2F;myapp &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The planner stage analyzes your project and creates a recipe file that describes your dependencies. The builder stage uses that recipe to compile dependencies before your source code is even copied in. This means the dependency compilation layer is cached as long as your dependencies do not change. In benchmarks, this alone can reduce build times from 34 seconds to 15 seconds when only source code changes, a reduction of more than 50 percent.&lt;&#x2F;p&gt;
&lt;p&gt;But cargo-chef has a limitation. Even with dependency compilation separated from source compilation, compiling dependencies is still treated as a single operation. If one dependency changes, all dependencies need to be recompiled. This is where combining cargo-chef with sccache becomes powerful. Sccache provides fine-grained caching at the compiler level, so only the specific crates that changed need to be recompiled while unchanged crates reuse their cached artifacts.&lt;&#x2F;p&gt;
&lt;p&gt;The optimal Dockerfile for Rust combines both tools with BuildKit cache mounts.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; rust:1.90 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo install cargo-chef sccache --locked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ENV&lt;&#x2F;span&gt;&lt;span&gt; RUSTC_WRAPPER=sccache SCCACHE_DIR=&#x2F;sccache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; Cargo.toml Cargo.lock .&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo chef prepare --recipe-path recipe.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=cache,target=&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;registry,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,target=&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;git,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cargo chef cook --release --recipe-path recipe.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; --mount=type=cache,target=&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;registry,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,target=&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;git,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --mount=type=cache,target=$SCCACHE_DIR,sharing=locked \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cargo build --release --bin app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; ubuntu:24.04 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; runtime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; groupadd -g 1001 appgroup &amp;amp;&amp;amp; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    useradd -u 1001 -g appgroup -m -d &#x2F;home&#x2F;appuser -s &#x2F;bin&#x2F;bash appuser&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=build --chown=appuser:appgroup &#x2F;app&#x2F;target&#x2F;release&#x2F;app &#x2F;usr&#x2F;local&#x2F;bin&#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;USER&lt;&#x2F;span&gt;&lt;span&gt; appuser&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ENTRYPOINT&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Three cache mounts are essential here. The &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;registry&lt;&#x2F;code&gt; mount caches downloaded crate files from crates.io. The &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;cargo&#x2F;git&lt;&#x2F;code&gt; mount caches git-based dependencies. The sccache directory caches individual compilation artifacts. The &lt;code&gt;sharing=locked&lt;&#x2F;code&gt; parameter ensures exclusive access during compilation, preventing cache corruption when parallel builds run.&lt;&#x2F;p&gt;
&lt;p&gt;With this combination, build times can drop from 34 seconds to 7 seconds, a reduction of more than 75 percent. The runtime stage uses a minimal Ubuntu image with a non-root user for security, copying only the compiled binary from the build stage.&lt;&#x2F;p&gt;
&lt;p&gt;For non-Docker Rust builds, sccache is the answer. Unlike caching the target directory, sccache caches individual compilation units by their hash. This means you get cache hits even across different branches or when dependencies change, as long as some of the same code is being compiled.&lt;&#x2F;p&gt;
&lt;p&gt;The way sccache works is by wrapping the Rust compiler and functioning like a shim. It intercepts all compilation requests inbound from cargo, derives a cache key from the request and its environment, then checks for its presence in the cache. A hit means the compilation task was previously completed, so sccache simply returns the cached result. With a miss, sccache forwards the call to rustc and caches the result for later. The key insight is that sccache stores artifacts in content addressable storage that works in ephemeral CI environments, unlike cargo’s built in caching which requires a persistent disk.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with using &lt;code&gt;actions&#x2F;cache&lt;&#x2F;code&gt; for Rust is that the target directory hoards artifacts from prior builds and grows uncontrollably without intervention. Even if you cull stale artifacts, the whole collection is handled as a coarse unit, and builds will regularly download a cache entry containing a subset of artifacts that are not useful. GitHub network transfer is notoriously slow, and each repo is limited to a total cache size of 10GB, which fills quickly when you are saving whole copies of the target directory at a time.&lt;&#x2F;p&gt;
&lt;p&gt;Setting up sccache in GitHub Actions is straightforward with the official action.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un sccache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ozilla-actions&#x2F;sccache-action@v0.0.7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ompile project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;CCACHE_GHA_ENABLED&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    R&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;USTC_WRAPPER&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sccache&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your first build will populate the cache, and successive builds should be much faster as those cache contents are utilized. The difference from the target directory approach is that sccache allows the build to begin immediately and concurrently fetches only what is necessary for the current build, rather than waiting for the whole cache blob to arrive upfront.&lt;&#x2F;p&gt;
&lt;p&gt;When things are not working as expected, &lt;code&gt;sccache -s&lt;&#x2F;code&gt; shows you what is happening. It prints statistics about cache hits, misses, and the reasons why certain compilations could not be cached.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Compile requests                      45&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Compile requests executed             33&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cache hits                            33&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cache hits (Rust)                     33&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cache misses                           0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cache hits rate                   100.00 %&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Non-cacheable calls                   11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Non-cacheable reasons:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;crate-type                            51&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;incremental                            2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The non-cacheable reasons section is where the debugging gold lives. The most common culprit is &lt;code&gt;crate-type&lt;&#x2F;code&gt;. Sccache can only cache &lt;code&gt;rlib&lt;&#x2F;code&gt; and &lt;code&gt;staticlib&lt;&#x2F;code&gt; crates. Binaries, dynamic libraries, and proc-macros all invoke the system linker and cannot be cached. If you see a lot of &lt;code&gt;crate-type&lt;&#x2F;code&gt; entries, that is expected behavior, not a bug. The &lt;code&gt;incremental&lt;&#x2F;code&gt; reason means cargo’s incremental compilation was enabled, which is incompatible with sccache. You need to set &lt;code&gt;CARGO_INCREMENTAL=0&lt;&#x2F;code&gt; to disable it.&lt;&#x2F;p&gt;
&lt;p&gt;For deeper debugging, enable logging with &lt;code&gt;SCCACHE_LOG=debug&lt;&#x2F;code&gt; and &lt;code&gt;SCCACHE_ERROR_LOG=&#x2F;tmp&#x2F;sccache.log&lt;&#x2F;code&gt;. The log will show exactly why each compilation was or was not cached, including the full cache key derivation. This is invaluable when you are getting unexpected cache misses. Common causes include absolute path mismatches between different build environments, compiler version changes, and feature flag combinations creating different cache keys.&lt;&#x2F;p&gt;
&lt;p&gt;There is a gotcha with the GitHub Actions backend though. For each invocation of rustc, sccache will ask the cache backend if the corresponding artifact exists. If your project is large and contains a lot of dependencies, this could end up being too chatty for GitHub’s liking. Sccache gracefully treats a 429 Too Many Requests response as a cache miss, as opposed to failing your build midway. But this is indeed a false miss, and the corresponding compilation time during periods of high activity could result in worse overall build performance. For large projects, using a dedicated cache backend like S3 or a WebDAV endpoint avoids these rate limits entirely.&lt;&#x2F;p&gt;
&lt;p&gt;The linker is another bottleneck that people often overlook. The default linker on Linux is slow, especially for large binaries with lots of dependencies. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rui314&#x2F;mold&quot;&gt;mold&lt;&#x2F;a&gt; is a modern linker that is dramatically faster. Switching to mold can cut link times from minutes to seconds for large projects.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; .cargo&#x2F;config.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;x86_64-unknown-linux-gnu&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;linker&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;clang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;rustflags&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-C&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;link-arg=-fuse-ld=mold&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The performance difference with mold is dramatic for large projects. Benchmarks on a simulated 16 core machine show mold linking MySQL 8.3 in 0.46 seconds compared to 10.84 seconds for GNU ld, 7.47 seconds for GNU gold, and 1.64 seconds for LLVM lld. For Clang 19, mold takes 1.35 seconds versus 42.07 seconds for GNU ld and 5.20 seconds for LLVM lld. Mold is so fast that it is only 2x slower than a simple &lt;code&gt;cp&lt;&#x2F;code&gt; command copying the same amount of data.&lt;&#x2F;p&gt;
&lt;p&gt;The reason mold is so much faster comes down to aggressive parallelization. Unlike other linkers that have sequential bottlenecks, mold uses Intel TBB to parallelize nearly all operations. It uses a data parallelism pattern where threads process data independently without communication, which scales efficiently across cores. For operations like build-id computation, mold splits work into parallel chunks and combines results using a map-reduce pattern.&lt;&#x2F;p&gt;
&lt;p&gt;However, mold only supports Linux. It cannot link macOS or Windows binaries. For macOS, there is a separate project called sold, but it is less mature. If your CI runs on Linux and you are building Linux binaries, mold is an easy win. If you need cross-platform support, you are stuck with lld.&lt;&#x2F;p&gt;
&lt;p&gt;In practice though, the mold linker showed negligible results for some codebases. Testing on the Zed editor codebase, mold was actually 0.7 percent slower than baseline when applied only to release builds. The linking phase is not always the bottleneck. For projects where compilation dominates, mold will not help much. Measure before assuming it will speed things up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nightly-compiler-features-for-faster-builds&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nightly-compiler-features-for-faster-builds&quot; aria-label=&quot;Anchor link for: nightly-compiler-features-for-faster-builds&quot;&gt;Nightly compiler features for faster builds&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Rust nightly compiler has several features that can speed up builds if you are willing to use an unstable toolchain. Two features in particular are worth knowing about.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;-Z share-generics&lt;&#x2F;code&gt; flag allows the compiler to share generic code across different compilation units. This can significantly reduce build times for projects that use a lot of generics, which is most Rust projects. The &lt;code&gt;-Z threads=8&lt;&#x2F;code&gt; flag allows the compiler to parse files and expand macros in parallel.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild with nightly features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    R&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;USTFLAGS&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-Z share-generics=y -Z threads=8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo +nightly build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Testing on the Zed codebase, nightly features provided a 7.3 percent overall improvement with build times dropping by 22.7 percent. The total time went from 28 minutes 36 seconds to 26 minutes 30 seconds. Test execution time stayed about the same, but the actual compilation was dramatically faster.&lt;&#x2F;p&gt;
&lt;p&gt;The key is that you must pass these flags via RUSTFLAGS, not just install the nightly toolchain. Simply switching to nightly without the flags gives you nothing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cranelift-is-not-ready-for-most-projects&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cranelift-is-not-ready-for-most-projects&quot; aria-label=&quot;Anchor link for: cranelift-is-not-ready-for-most-projects&quot;&gt;Cranelift is not ready for most projects&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Cranelift is an alternative compiler backend for Rust that trades runtime performance for faster compilation. It is designed for JIT compilation scenarios where compilation latency matters more than the speed of the generated code. The Rust compiler has experimental support for Cranelift via the &lt;code&gt;rustc_codegen_cranelift&lt;&#x2F;code&gt; component.&lt;&#x2F;p&gt;
&lt;p&gt;The appeal is obvious. Cranelift compiles about 20 to 40 percent faster than LLVM. For debug builds and test runs where you do not care about runtime performance, this sounds like a free speedup. But in practice, Cranelift fails to compile many real-world codebases.&lt;&#x2F;p&gt;
&lt;p&gt;The most common failure is inline assembly. Cranelift does not fully support &lt;code&gt;asm!&lt;&#x2F;code&gt; and &lt;code&gt;global_asm!&lt;&#x2F;code&gt; sym operands. Any project that depends on crates using inline assembly will fail to compile. This includes wasmtime, many crypto crates, and anything doing low-level system programming.&lt;&#x2F;p&gt;
&lt;p&gt;Testing on the Zed codebase, Cranelift failed with the error &lt;code&gt;asm! and global_asm! sym operands are not yet supported&lt;&#x2F;code&gt; when trying to compile wasmtime-fiber. This is a known limitation that exists regardless of whether you use stable or nightly Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Other limitations include incomplete debugger support where local variables cannot be inspected, partial SIMD intrinsics support, and ABI compatibility issues when mixing Cranelift and LLVM compiled code. The Cranelift team is targeting production readiness for late 2025, but for now it is not a viable option for most projects.&lt;&#x2F;p&gt;
&lt;p&gt;The safe use cases for Cranelift are projects without inline assembly dependencies, without heavy SIMD usage, and where you do not need debugger support. For everything else, stick with LLVM.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cargo-nextest-is-the-biggest-single-optimization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cargo-nextest-is-the-biggest-single-optimization&quot; aria-label=&quot;Anchor link for: cargo-nextest-is-the-biggest-single-optimization&quot;&gt;cargo-nextest is the biggest single optimization&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you only make one change to your Rust CI, make it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nexte.st&#x2F;&quot;&gt;cargo-nextest&lt;&#x2F;a&gt;. It is a next-generation test runner that can be up to 3x faster than &lt;code&gt;cargo test&lt;&#x2F;code&gt;. The speedup comes from a fundamentally different execution model.&lt;&#x2F;p&gt;
&lt;p&gt;With &lt;code&gt;cargo test&lt;&#x2F;code&gt;, test binaries run serially. Each binary runs its tests in parallel internally, but if one binary has a slow test, everything waits. If you have 20 tests where 19 take less than 5 seconds but one takes 60 seconds, the entire binary takes 60 seconds. Cargo cannot start other binaries during those idle 55 seconds.&lt;&#x2F;p&gt;
&lt;p&gt;Nextest runs each test in a separate process. It first queries all test binaries to enumerate every test, then runs them all in parallel across all binaries simultaneously. While that 60 second test runs, all other tests from all binaries can execute in parallel. This eliminates the long-pole test problem that plagues large test suites.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nstall nextest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;aiki-e&#x2F;install-action@nextest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo nextest run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Testing on the Zed codebase with warm sccache, nextest delivered a 35 percent speedup. Total time dropped from 28 minutes 36 seconds to 18 minutes 34 seconds. Test execution specifically went from 15 minutes 10 seconds to 10 minutes 46 seconds, a 28.9 percent improvement.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond raw speed, nextest has features designed for CI. It outputs JUnit XML for test reporting integrations. It supports test partitioning for sharding across multiple runners. It can archive test binaries for running on different machines. It has configurable retries with exponential backoff for flaky tests. It can identify and terminate slow tests that exceed a timeout.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; .config&#x2F;nextest.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ci&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;retries&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;slow-timeout&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; period&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;60s&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; terminate-after&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ci&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;junit&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;junit.xml&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The main limitation is that nextest does not support doctests due to limitations in stable Rust. You need to run doctests separately with &lt;code&gt;cargo test --doc&lt;&#x2F;code&gt;. For most projects this is a minor inconvenience compared to the speedup on unit and integration tests.&lt;&#x2F;p&gt;
&lt;p&gt;One thing to watch out for is that nextest with a cold sccache is actually 16.8 percent slower than baseline. The cache warming strategy matters. With a warm cache, you get the 35 percent speedup. With a cold cache, you pay the overhead of the process-per-test model without the caching benefits. Make sure your CI is actually getting cache hits before celebrating the nextest migration.&lt;&#x2F;p&gt;
&lt;p&gt;Profile-guided optimization is another technique that can help, though it is more complex to set up. The idea is to compile your code with instrumentation, run your test suite to collect profiling data, then recompile with that data to guide optimization decisions. This can produce faster binaries, but it also means your CI needs to do two compilation passes.&lt;&#x2F;p&gt;
&lt;p&gt;One more thing that helps is being strategic about what you build in CI. Do you really need to run &lt;code&gt;cargo build --release&lt;&#x2F;code&gt; on every PR? Release builds are much slower than debug builds because of all the optimization passes. For most CI purposes, a debug build plus running tests is sufficient. Save the release build for when you are actually deploying.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fuzzing-in-ci&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fuzzing-in-ci&quot; aria-label=&quot;Anchor link for: fuzzing-in-ci&quot;&gt;Fuzzing in CI&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With agents writing more code, I have found myself adding more sophisticated testing strategies like fuzzing. This technique helped me find several bugs that unit tests would never have caught. Fuzzing is automated testing with weird inputs. You ask the fuzzer to exercise some code, prime it with a few seed inputs, and let it mutate them forever. Most of the inputs are garbage, and that is the whole point. The fuzzer keeps the cases that reach new code paths and keeps pushing on whatever looks interesting or seems to take more time.&lt;&#x2F;p&gt;
&lt;p&gt;Fuzzing is great for parsers, decoders, protocol handlers, and anything else that sees untrusted input. It can find problems like bad lengths, duplicate fields, giant counts, and broken UTF-8. These are not typically written in run of the mill unit tests. The fuzzer will continually try out new inputs forever.&lt;&#x2F;p&gt;
&lt;p&gt;For Rust projects, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-fuzz.github.io&#x2F;book&#x2F;cargo-fuzz.html&quot;&gt;cargo fuzz&lt;&#x2F;a&gt; wraps libFuzzer to find inputs that hit new code paths. When it finds those inputs, it saves them into a corpus. The longer the corpus grows, the deeper the fuzzer can reach. If you start cold without a corpus every run, you throw away that progress. A corpus is an artifact about your system that you want to keep around.&lt;&#x2F;p&gt;
&lt;p&gt;The simplest way to run fuzzing in CI is as a smoke test. Build and run your fuzz targets for a small amount of time on every push.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uzz&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;buntu-latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;trategy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atrix&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uzz_target&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y_first_target&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y_second_target&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ustup default nightly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo install cargo-fuzz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo fuzz build ${{ matrix.fuzz_target }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo fuzz run ${{ matrix.fuzz_target }} -- -max_total_time=300&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;upload-artifact@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ailure()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzzing-artifacts-${{ matrix.fuzz_target }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz&#x2F;artifacts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But fuzzing gets much better when it keeps its corpus and just keeps running. It gets even better when several runners explore in parallel. More runners means more total executions, which usually means more chances to find new coverage.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a diversity benefit. One runner can get stuck wandering in an uninteresting corner of the input space. Several runners tend to wander in different directions. Coverage guided fuzzers can settle into local minima. Several machines seem to make it more likely to find a useful input.&lt;&#x2F;p&gt;
&lt;p&gt;Distributing also helps when the target is memory hungry. Fuzzing can eat memory fast. One machine runs out of room sooner than you think. With multiple machines, crashes stay isolated. If one machine dies, the others keep going.&lt;&#x2F;p&gt;
&lt;p&gt;The setup for distributed fuzzing uses the GitHub Actions cache to keep the corpus around. Caching is write once per key but can be searched by a prefix. You save the corpus with a unique key per run and restore it with a prefix match.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;estore corpus from cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;cache&#x2F;restore@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz&#x2F;corpus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz-corpus-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;estore-keys&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      fuzz-corpus-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; After fuzzing...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cho &amp;quot;ts=$(date +%s)&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ave corpus to cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;cache&#x2F;save@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz&#x2F;corpus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz-corpus-${{ steps.ts.outputs.ts }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On restore, the prefix grabs the newest cache entry. After the run, you save with a fresh key using a timestamp. Old corpus entries age out when the cache is over size, so you get a rolling corpus history without too much extra storage.&lt;&#x2F;p&gt;
&lt;p&gt;The fan out part uses a matrix job. Start N runners, each one restores the same corpus and fuzzes for a fixed time. Each shard starts from the same place, but libFuzzer still sends them down different paths. The &lt;code&gt;-fork=$(nproc)&lt;&#x2F;code&gt; flag also uses every core inside each runner, so you get parallelism across shards and inside each shard.&lt;&#x2F;p&gt;
&lt;p&gt;After the shards finish, a merge job downloads the findings and folds them back into the corpus. libFuzzer has a built in merge mode that keeps only the inputs that add coverage.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erge&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eeds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uzz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lways() &amp;amp;&amp;amp; !cancelled()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; D&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ownload all findings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;download-artifact@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;attern&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;indings-*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ll_findings&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erge-multiple&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; M&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;erge into corpus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;argo fuzz run my_target fuzz&#x2F;corpus all_findings&#x2F;* -- -merge=1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;if: always() &amp;amp;&amp;amp; !cancelled()&lt;&#x2F;code&gt; guard makes the merge job run even if one shard fails, so successful shards still contribute findings.&lt;&#x2F;p&gt;
&lt;p&gt;Running this on a cron keeps the corpus growing. Every six hours, four runners fuzz for 10 minutes, then the merge job rolls their work forward. That is enough time to make steady progress without turning the workflow into a budget fire. Over time the corpus turns into a useful set of tests you did not have to dream up yourself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;monorepo-or-not&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#monorepo-or-not&quot; aria-label=&quot;Anchor link for: monorepo-or-not&quot;&gt;Monorepo or not?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The monorepo versus polyrepo debate has been going on for years, and CI is where the tradeoffs become most apparent. A monorepo puts all your code in one repository. A polyrepo splits it across multiple repositories, typically one per service or package. Both approaches have passionate advocates, and both have real CI implications.&lt;&#x2F;p&gt;
&lt;p&gt;The appeal of a monorepo is simplicity in some dimensions. One repository to clone, one place to make cross-cutting changes, one CI configuration to maintain. If you need to update a shared library and all the services that use it, you can do it in a single PR. Refactoring across service boundaries becomes a normal code change rather than a multi-repository coordination exercise.&lt;&#x2F;p&gt;
&lt;p&gt;But monorepos create CI challenges. When everything is in one repository, a naive CI setup will build and test everything on every commit. This does not scale. Google famously has a monorepo with billions of lines of code, but they also have a custom build system (Bazel) and massive infrastructure to make it work. Most teams do not have that.&lt;&#x2F;p&gt;
&lt;p&gt;The solution is affected-based builds. Instead of building everything, you figure out what changed and only build and test the affected parts. GitHub Actions supports this through path filters on workflow triggers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;aths&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;services&#x2F;api&#x2F;**&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;packages&#x2F;shared&#x2F;**&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This workflow only runs when files in those directories change. You can have separate workflows for different parts of your monorepo, each triggered by changes to its relevant paths. The downside is that you need to maintain these path filters, and they can get out of sync with your actual dependency graph.&lt;&#x2F;p&gt;
&lt;p&gt;Tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nx.dev&#x2F;&quot;&gt;Nx&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turbo.build&#x2F;&quot;&gt;Turborepo&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bazel.build&#x2F;&quot;&gt;Bazel&lt;&#x2F;a&gt; take this further by understanding the dependency graph of your monorepo. They can automatically determine what is affected by a change and only build and test those parts. They also provide distributed caching, so if someone else already built a particular package with the same inputs, you can reuse their output.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild affected&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;px nx affected --target=build --base=origin&#x2F;main&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;affected&lt;&#x2F;code&gt; command compares your current branch to main and figures out what changed. It then builds only the projects that are affected by those changes, either directly or through dependencies. This can turn a 30 minute full build into a 2 minute incremental build.&lt;&#x2F;p&gt;
&lt;p&gt;For very large repositories, even cloning can be slow. Git sparse checkout lets you clone only the parts of the repository you need. Combined with shallow clones that only fetch recent history, you can dramatically reduce checkout times.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;parse-checkout&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      services&#x2F;api&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      packages&#x2F;shared&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etch-depth&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The polyrepo approach avoids these problems by keeping repositories small and focused. Each repository has its own CI that only cares about that code. The tradeoff is coordination. Cross-repository changes require multiple PRs, and keeping dependencies in sync becomes a versioning problem. You need good tooling for dependency management, and changes that span repositories are harder to review atomically.&lt;&#x2F;p&gt;
&lt;p&gt;There is no universally right answer. Small teams often do fine with a monorepo and simple CI. Large organizations with many teams often benefit from polyrepos with clear ownership boundaries. The worst situation is a monorepo without the tooling to make it work, where every PR triggers a full build of everything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accelerating-test-suites&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#accelerating-test-suites&quot; aria-label=&quot;Anchor link for: accelerating-test-suites&quot;&gt;Accelerating test suites&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;CI bottlenecks have always dragged on team velocity, but agentic coding raised the stakes. When agents write a good chunk of the code, your pipeline runs many more times per day, and every wasted minute gets multiplied across all of those runs. Speeding up your pipelines is not one heroic refactor. It is a process of finding the next bottleneck, fixing it, and moving on to the next one.&lt;&#x2F;p&gt;
&lt;p&gt;The test suite is usually the first bottleneck teams hit. There are two ways to speed it up that sound similar but mean different things. Parallel testing runs tests across multiple CPUs on a single machine. You scale the tests horizontally by scaling the box vertically with a bigger runner and more workers. Sharded testing breaks the suite into slices and runs each slice on its own machine. Twelve shards means twelve runners, each running a twelfth of the suite.&lt;&#x2F;p&gt;
&lt;p&gt;Parallel testing is the most underrated option in CI. It needs no infrastructure, no matrix, and no result merging, yet most suites do not use it fully. Playwright for example does not run tests in parallel on CI by default. The config that npm init playwright generates sets workers to 1 when the CI environment variable is set. Every test runs one at a time on exactly the machines where speed matters most.&lt;&#x2F;p&gt;
&lt;p&gt;The default exists to keep shared state tests from flaking. Two tests that touch the same database row or the same signed in user can step on each other when they run simultaneously. Tests that do not share mutable state are isolated, and isolated tests can safely run with as many workers as the machine has cores. A similar pattern hides in Go. The command &lt;code&gt;go test .&#x2F;...&lt;&#x2F;code&gt; runs packages in parallel, but tests inside a package run serially unless they opt in with &lt;code&gt;t.Parallel()&lt;&#x2F;code&gt;. A serial suite on a 16 core runner leaves fifteen cores idle.&lt;&#x2F;p&gt;
&lt;p&gt;How do you know if you are using the right size machine? Look at the resource graphs. If CPU peaks at 30 percent, the fix is more workers, not a bigger runner. If CPU sits at 100 percent while tests slow down, the runner is too small for the worker count. Tune workers and runner size until the machine is saturated. You pay for the whole machine, not for the part you use.&lt;&#x2F;p&gt;
&lt;p&gt;Sharding breaks through the ceiling when parallelism maxes out. A single machine only gets so big, and many test suites stop scaling with cores long before that because they bottleneck on a shared database or on I&#x2F;O. With sharding, each slice runs on its own machine autonomously.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;trategy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ail-fast&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atrix&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;hard&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;laywright test --shard=${{ matrix.shard }}&#x2F;6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is the catch. Every CI job pays a setup cost before a single test runs. Checkout, language runtimes, dependencies, browsers, service containers, seed data. That cost is fixed per machine, which means sharding multiplies it. Think about this as job density, the fraction of a job’s wall time spent doing the work the job exists for. For a test job that is running tests. Everything else like setup, downloads, and cache restores is overhead you pay for but learn nothing from.&lt;&#x2F;p&gt;
&lt;p&gt;Sharding dilutes density. A single job with 3 minutes of setup and 60 minutes of tests sits at 95 percent density. Split those same tests across twelve shards and each one runs 5 minutes of tests behind the same 3 minutes of setup. Density drops to 62 percent. Your wall clock improves, but more than a third of every billed minute is now overhead, and each additional shard makes it worse.&lt;&#x2F;p&gt;
&lt;p&gt;The rule of thumb is to shard as wide as you want, as long as every shard stays above roughly 80 percent job density. Put differently, each shard should spend at least four times as long testing as it does setting up. For a 60 minute suite with 3 minutes of setup, each shard needs at least 12 minutes of tests to stay above the line, so the suite tops out around 5 shards.&lt;&#x2F;p&gt;
&lt;p&gt;The lever is setup time, not shard count. Drop setup from 45 seconds to 15 by building images once and snapshotting the toolchain into a custom runner image, and the same suite can shard much wider before it starts to hurt.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-independent-steps-in-parallel&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-independent-steps-in-parallel&quot; aria-label=&quot;Anchor link for: running-independent-steps-in-parallel&quot;&gt;Running independent steps in parallel&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;CI workflows often start as a linear sequence. Check out your repo, install your dependencies, start your services, wait for them to be ready, and then run your tests. Within a single job, steps usually run one after the other, even when that work is independent and does not rely on previous steps.&lt;&#x2F;p&gt;
&lt;p&gt;One optimization is to stop treating a CI job like one long serial shell script. Consider a workflow with three independent pieces of work. Linting, unit tests, and a database backed integration test suite. The linting and unit tests do not need the database while the integration tests do. None of these three units of work depend on each other. That gives you an optimization target. Overlap the unit tests and linting with database startup and integration test execution instead of running everything sequentially.&lt;&#x2F;p&gt;
&lt;p&gt;The simplest approach is to start services early and defer the readiness wait until you actually need them. If you are using docker run with the detached flag to start services, move that step before the linting so the database is starting up while the following steps run. Then wait for readiness only right before the integration tests.&lt;&#x2F;p&gt;
&lt;p&gt;You can go further by running the lint, unit tests, and integration work concurrently using background shell commands.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; R&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;un all tests in parallel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    set -euo pipefail&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_lint() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      npm run lint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_unit_tests() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      npm test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_integration_tests() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      .&#x2F;wait-for-db.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      npm run test:integration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_lint &amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    LINT_PID=$!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_unit_tests &amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    UNIT_PID=$!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    run_integration_tests &amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    INTEGRATION_PID=$!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    STATUS=0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    wait $LINT_PID || STATUS=$?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    wait $UNIT_PID || STATUS=$?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    wait $INTEGRATION_PID || STATUS=$?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    exit $STATUS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the linting, unit tests, and integration work all run at the same time. The integration branch still owns the database dependency. It waits for the database to become ready and then runs the integration tests.&lt;&#x2F;p&gt;
&lt;p&gt;The workflow is starting to turn into a mini process manager though. You have to define shell functions, start background processes, track process IDs, decide where to wait, and preserve the right exit status. The more work you parallelize this way, the less the workflow reads like a workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Some CI platforms support parallel steps as a first class concept in the workflow syntax. You can wrap independent steps in a parallel block and the platform handles the process management for you. Each branch in the parallel group starts from the same job state, runs at the same time, and merges back into the job before moving on to the next step.&lt;&#x2F;p&gt;
&lt;p&gt;The best candidates for parallel steps are units of work that are genuinely independent. Be careful with branches that write to the same files, mutate the same dependency directory, or depend on each other’s side effects. Those probably should not be separate parallel branches.&lt;&#x2F;p&gt;
&lt;p&gt;Resource constraints matter too. Parallelism improves wall clock time by overlapping work, but heavy steps can still compete for CPU, filesystem, and cache resources when they run at the same time. You might see individual steps take longer even though the total job time drops. That is the tradeoff.&lt;&#x2F;p&gt;
&lt;p&gt;The matrix strategy is particularly powerful for building multiple Docker images in a monorepo. Instead of building images sequentially or writing complex parallel shell scripts, you define a matrix of configurations and let GitHub Actions fan out the work automatically.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uild&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;trategy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atrix&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ockerfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dockerfile.api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dockerfile.worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dockerfile.web&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nclude&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ockerfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; D&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ockerfile.api&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;services&#x2F;api&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ockerfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; D&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ockerfile.worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;services&#x2F;worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ockerfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; D&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ockerfile.web&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;            c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;services&#x2F;web&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;checkout@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&#x2F;build-push-action@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;        w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ matrix.context }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ matrix.dockerfile }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The include key lets you attach additional values to each matrix entry. Here we are specifying the build context for each Dockerfile so each image builds from its own directory. All three images build in parallel on separate runners, and the total wall clock time is roughly the time of the slowest build rather than the sum of all builds.&lt;&#x2F;p&gt;
&lt;p&gt;You can also use multi-dimensional matrices for more complex scenarios. If you need to build each image for multiple platforms, you can add a platform dimension.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;trategy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atrix&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ockerfile&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dockerfile.api&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Dockerfile.worker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;latform&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;linux&#x2F;amd64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;linux&#x2F;arm64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates four jobs, one for each combination of Dockerfile and platform. The &lt;code&gt;fail-fast&lt;&#x2F;code&gt; option controls what happens when one job fails. By default it is true, which cancels all in-flight jobs when one fails. Set it to false if you want all jobs to complete regardless of failures, which is useful when you want to see all the errors at once rather than fixing them one at a time.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;max-parallel&lt;&#x2F;code&gt; option limits how many matrix jobs run simultaneously. This is useful when your jobs compete for shared resources or when you want to avoid overwhelming external services. Without a limit, GitHub Actions will run as many jobs in parallel as your plan allows.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-things-go-wrong&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-things-go-wrong&quot; aria-label=&quot;Anchor link for: when-things-go-wrong&quot;&gt;When things go wrong&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Debugging CI failures is one of the most frustrating parts of software development. The build works locally but fails in CI. The error message is cryptic. You cannot SSH into the runner to poke around. You push a fix, wait 10 minutes for CI to run, and it fails again with a different error. This cycle can eat hours.&lt;&#x2F;p&gt;
&lt;p&gt;The first line of defense is good logging. GitHub Actions captures stdout and stderr from your commands, but you need to actually print useful information. For Docker builds, the &lt;code&gt;--progress=plain&lt;&#x2F;code&gt; flag gives you full build output instead of the fancy animated display. For test failures, make sure your test framework outputs enough context to understand what went wrong.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker build --progress=plain -t myapp .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nektos&#x2F;act&quot;&gt;act&lt;&#x2F;a&gt; tool lets you run GitHub Actions workflows locally. It spins up Docker containers that mimic the GitHub runner environment and executes your workflow steps. This is not perfect because the local environment is never exactly the same as GitHub’s runners, but it catches a lot of issues without the push-wait-fail cycle.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;act&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;GitHub’s job summaries feature is underused. You can write markdown to &lt;code&gt;$GITHUB_STEP_SUMMARY&lt;&#x2F;code&gt; and it appears on the workflow run page. This is great for surfacing important information like test results, coverage reports, or build artifacts without digging through logs.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;est summary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;## Test Results&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;- Passed: 142&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;- Failed: 0&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For more sophisticated debugging, OpenTelemetry is starting to show up in CI systems. The idea is to instrument your build process the same way you would instrument a production service, with traces that show where time is being spent and what depends on what. Several observability platforms support ingesting CI traces, and there are open source options too.&lt;&#x2F;p&gt;
&lt;p&gt;BuildKit itself can export traces in OpenTelemetry format, showing you exactly how long each layer took to build and what was cached versus rebuilt. This is invaluable for understanding why a build is slow.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild with tracing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    docker buildx build \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      --progress=plain \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      --metadata-file=metadata.json \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;      -t myapp .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One pattern that helps with flaky tests is automatic retries with different strategies. Some tests fail due to timing issues or external dependencies. Rather than marking the whole build as failed, you can retry just the failed tests.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;est with retry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ick-fields&#x2F;retry@v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imeout_minutes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ax_attempts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pm test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The danger with retries is that they can mask real problems. A test that fails 30% of the time is not fine just because it eventually passes. You should track flaky tests and fix them, not just retry until they pass. Flaky tests are especially painful with merge queues because a flake in a five PR group evicts the entire batch and rebuilds it.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions does not have a native way to cancel all jobs when one fails. The &lt;code&gt;fail-fast&lt;&#x2F;code&gt; option only works within a matrix strategy, not across separate jobs. Some teams work around this with sentinel cancel jobs that watch for failures and cancel the workflow run via the API.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ancel-if-build-failed&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eeds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ailure()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;buntu-latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ermissions&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ctions&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; w&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ancel workflow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;        curl -fsSL -X POST \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          -H &amp;quot;Authorization: Bearer ${{ github.token }}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;          &amp;quot;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;${{ github.repository }}&#x2F;actions&#x2F;runs&#x2F;${{ github.run_id }}&#x2F;cancel&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This adds boilerplate but prevents wasting compute on jobs that are doomed to fail anyway.&lt;&#x2F;p&gt;
&lt;p&gt;Artifact uploads are essential for debugging failures that only happen in CI. Upload logs, screenshots, core dumps, or whatever else might help diagnose the issue. GitHub keeps artifacts for 90 days by default, which is usually enough time to investigate.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pload logs on failure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ailure()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ctions&#x2F;upload-artifact@v4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ebug-logs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;var&#x2F;log&#x2F;myapp&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-economics-of-ci&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-economics-of-ci&quot; aria-label=&quot;Anchor link for: the-economics-of-ci&quot;&gt;The economics of CI&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;CI costs money, and at scale it can cost a lot of money. Understanding the economics helps you make better decisions about where to invest in optimization.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions pricing is based on compute minutes. The free tier gives you 2,000 minutes per month for private repositories, which sounds like a lot until you realize that a 20 minute build running on every push adds up quickly. A team of 10 developers pushing a few times a day can easily burn through that in a week.&lt;&#x2F;p&gt;
&lt;p&gt;The paid tiers charge per minute, with different rates for different runner types. Linux runners are cheapest, macOS runners are about 10x more expensive, and Windows runners are somewhere in between. Larger runners with more CPU and memory cost more per minute but might finish faster, so the total cost could be lower.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Standard Linux runner: $0.008 per minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Large Linux runner (4 cores): $0.016 per minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;macOS runner: $0.08 per minute&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The math gets interesting when you consider that a faster runner might cut your build time in half. If your build takes 20 minutes on a standard runner and 10 minutes on a large runner, the large runner actually costs the same total amount while giving you faster feedback. The real savings come from developer time not spent waiting.&lt;&#x2F;p&gt;
&lt;p&gt;Self-hosted runners change the economics completely. You pay for the infrastructure instead of per-minute charges. For teams with high CI volume, this can be dramatically cheaper. A dedicated build server running 24&#x2F;7 costs a fixed amount regardless of how many builds you run. The tradeoff is operational overhead and the need to manage capacity.&lt;&#x2F;p&gt;
&lt;p&gt;Third-party runner services sit in between. They provide managed runners that are faster than GitHub’s hosted runners, with better caching and sometimes native Arm support. The pricing is typically per-minute like GitHub but with different rates and capabilities. Some optimize specifically for Docker builds with persistent layer caches, fast SSD storage, and direct connections to container registries. For teams that spend a lot of time on Docker builds, the time savings can easily justify the cost.&lt;&#x2F;p&gt;
&lt;p&gt;The hidden cost that people often miss is developer productivity. If your CI takes 30 minutes, developers either context switch to something else (and lose focus) or sit there waiting (and waste time). Cutting that to 5 minutes has a real productivity impact that is hard to measure but very real.&lt;&#x2F;p&gt;
&lt;p&gt;Cache storage is another cost factor. GitHub Actions gives you 10GB of cache storage per repository. If you need more, you either need to be clever about what you cache or use external storage like S3. The cache eviction policy means old caches get deleted when you hit the limit, which can cause unexpected cache misses.&lt;&#x2F;p&gt;
&lt;p&gt;The optimization ROI calculation is straightforward. If you spend 8 hours optimizing your CI and it saves 10 minutes per build, and you run 50 builds per day, you break even in about 10 days. After that, it is pure savings. The hard part is knowing which optimizations will actually help and how much.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-copy-link-trap&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-copy-link-trap&quot; aria-label=&quot;Anchor link for: the-copy-link-trap&quot;&gt;The COPY –link trap&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Earlier I mentioned that &lt;code&gt;COPY --link&lt;&#x2F;code&gt; can prevent cascading cache invalidation. That is true in theory, but in practice it often increases build times rather than decreasing them. The intended purpose is to create layers independent of the parent image, so if the base image changes, the COPY layer does not need recomputation. But the implementation has hidden costs.&lt;&#x2F;p&gt;
&lt;p&gt;When you use a normal COPY, BuildKit creates a straightforward build graph. The build context feeds into the base image which feeds into the COPY layer. With &lt;code&gt;COPY --link&lt;&#x2F;code&gt;, BuildKit actually creates two separate build graphs that must be merged at the end. The COPY instruction builds in isolation on top of scratch, not on top of your base image. So what looks like one build is actually two parallel builds that get merged together.&lt;&#x2F;p&gt;
&lt;p&gt;This merging takes time. Two build graphs have to be created, a virtual stage from scratch has to be executed, and then the graphs have to be merged back together. For simple Dockerfiles, this overhead can make builds slower than just using regular COPY.&lt;&#x2F;p&gt;
&lt;p&gt;There are also bugs in BuildKit’s cache garbage collection algorithm with &lt;code&gt;COPY --link&lt;&#x2F;code&gt;. The garbage collector sometimes believes that cache artifacts from linked copies are 0 bytes in size rather than their actual size on disk. This leads to incorrect cache behavior and potential build issues that are hard to diagnose.&lt;&#x2F;p&gt;
&lt;p&gt;The legitimate use case for &lt;code&gt;COPY --link&lt;&#x2F;code&gt; is rebasing images when base images are updated. BuildKit can skip pushes and pulls of layers that are already present and reorder layers so the image manifest contains new and old layers in the correct order. But even in this case, full rebuilds with traditional COPY are often faster for most workloads.&lt;&#x2F;p&gt;
&lt;p&gt;The recommendation from teams that have run millions of builds is to avoid &lt;code&gt;COPY --link&lt;&#x2F;code&gt; unless you have a specific rebasing use case and have benchmarked it against regular COPY. The performance of linked copies should theoretically be better or equivalent, but the reality is that the implementation overhead often makes things worse.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;compression-matters-more-than-you-think&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#compression-matters-more-than-you-think&quot; aria-label=&quot;Anchor link for: compression-matters-more-than-you-think&quot;&gt;Compression matters more than you think&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When you pull or push a Docker image, what actually happens is that Docker retrieves a manifest from the registry containing a list of layers, then downloads those layers as compressed tarballs. By default, Docker compresses layers with gzip before sending them to the registry. But gzip is showing its age.&lt;&#x2F;p&gt;
&lt;p&gt;Gzip is a wrapper around the DEFLATE algorithm that has been the standard for general compression since the 90s. It works by concatenating files together as a tar before compressing them. The problem is that gzip is single threaded. For one reason or another, probably for compatibility due to how ubiquitous and long standing gzip is, gzip has not been updated to take advantage of modern multi core processors.&lt;&#x2F;p&gt;
&lt;p&gt;There is a parallel implementation called pigz that can use multiple cores when compressing or decompressing files. Containerd will use pigz for decompression if it is installed on the host machine. But here is the catch. Docker still uses single stream gzip for compression by default, even when pigz is available. The reason is ecosystem compatibility. Both gzip and pigz produce correct layers, but they arrive at their tarballs slightly differently and produce different sizes and hashes for identical uncompressed content. When pushed to a registry, they are recognized as different images. Docker prefers canonical images in Docker Hub at the expense of slower compression speeds.&lt;&#x2F;p&gt;
&lt;p&gt;Zstandard, or zstd, was developed by Facebook in 2015 and open sourced a year later. Unlike gzip, zstd is natively multi threaded. It was designed to provide similar compression ratios to gzip but with much faster decompression speeds. And the benchmarks back this up.&lt;&#x2F;p&gt;
&lt;p&gt;In tests compressing a large Docker image on a 16 core machine, zstd decompression was nearly 60 percent faster than pigz while producing a smaller file than gzip in the compression stage. The compression times for pigz and default zstd are within margin of error, but the decompression advantage is dramatic. This matters because decompression happens every time you pull an image, which is usually more frequent than pushing.&lt;&#x2F;p&gt;
&lt;p&gt;You can enable zstd compression in your builds by setting the output flag.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker&#x2F;build-push-action@v5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  w&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ags&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yapp:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;utputs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ompression=zstd,oci-mediatypes=true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;oci-mediatypes=true&lt;&#x2F;code&gt; is important because zstd requires OCI media types rather than the older Docker media types. Not all registries support zstd equally, so check your registry’s documentation. But for registries that do support it, switching to zstd is an easy win. Your pods start roughly twice as fast because decompression is so much quicker.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparing-ci-providers-for-docker&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#comparing-ci-providers-for-docker&quot; aria-label=&quot;Anchor link for: comparing-ci-providers-for-docker&quot;&gt;Comparing CI providers for Docker&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Not all CI providers are created equal when it comes to Docker builds. The differences in caching, BuildKit support, and multi platform capabilities can make a huge difference in build times and costs.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions fully supports BuildKit, which is critical for efficient Docker builds. But the caching story is weak. The GitHub Actions cache is backed by Azure Blob Storage with limited bandwidth between the runner and the cache. The 10GB per repository limit is a real constraint for larger projects. Once you hit the limit, GitHub evicts old caches using LRU, which can break layer dependencies and force full rebuilds. Multi platform builds require emulation because GitHub hosted runners are single architecture, and emulation can be up to 40x slower than native builds.&lt;&#x2F;p&gt;
&lt;p&gt;CircleCI has a built in Docker layer caching feature that uses volumes instead of object storage. This is significantly faster than the object storage approach because there is no network transfer. The cache limit is around 50GB per project, much larger than GitHub’s 10GB. The catch is that Docker layer caching costs extra on top of your base plan. Multi platform builds still require emulation, and you need manual configuration for buildx to work properly with the caching.&lt;&#x2F;p&gt;
&lt;p&gt;Google Cloud Build supports BuildKit but has no persistent cache between builds. You have to use registry based caching, which means pulling the latest image and using the cache-from parameter on every build. This works but is slow because you are transferring layers over the network every time. There is also no ARM compute, so multi platform builds require emulation.&lt;&#x2F;p&gt;
&lt;p&gt;Bitbucket Pipelines is the most limited option. It does not fully support buildx or BuildKit, which means it cannot handle multi platform builds at all. The cache limit is only 1GB, which is almost useless for Docker builds. The only workaround is registry based caching, which has the same network transfer problems as Google Cloud Build.&lt;&#x2F;p&gt;
&lt;p&gt;GitLab CI&#x2F;CD has different tradeoffs depending on whether you use their SaaS hosted runners or self hosted runners. The SaaS runners support BuildKit with privileged Docker daemon access, but there is no persistent Docker layer cache. You are stuck with the registry approach. Self hosted runners can have persistent caches, but they come with security risks. The shell executor requires granting the gitlab-runner user full root permissions. Docker in Docker gives each job its own Docker Engine instance with no layer caching between them. Binding to the Docker socket exposes the underlying host to privilege escalation.&lt;&#x2F;p&gt;
&lt;p&gt;Jenkins and Buildkite are self hosted options that give you full control but require you to manage the infrastructure. The security risks are the same as GitLab self hosted. You have to choose between accepting those risks or accepting slower build times from isolated builds.&lt;&#x2F;p&gt;
&lt;p&gt;The cost differences add up quickly. A team running 100 builds per day with 3 jobs of 8 minutes each on GitHub Actions 32 core runners at 0.128 dollars per minute spends about 6900 dollars per month on compute alone. Add 700 dollars for 3TB of cache storage and 280 dollars for data transfer between Azure and AWS, and you are at nearly 8000 dollars per month. Indirect costs like slow cache operations and per minute billing rounding can add another 800 dollars.&lt;&#x2F;p&gt;
&lt;p&gt;The per minute billing rounding is particularly sneaky. GitHub rounds up to the nearest minute per job. Three jobs of 20 seconds each get billed as 3 minutes, not 1 minute. This 300 percent increase affects workflows with many short jobs.&lt;&#x2F;p&gt;
&lt;p&gt;The fundamental insight is that none of the major CI providers offer native multi platform builds without emulation or running your own BuildKit instance. The trade off is between security with isolated builds and performance with persistent caches and native architectures. Teams that need both usually end up with third party services that specialize in Docker builds, running dedicated infrastructure with persistent NVMe caches and native builders for both Intel and ARM.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-is-this-all-going&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-is-this-all-going&quot; aria-label=&quot;Anchor link for: where-is-this-all-going&quot;&gt;Where is this all going?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;CI is evolving rapidly, and some interesting trends are emerging that will shape how we build and test software in the coming years.&lt;&#x2F;p&gt;
&lt;p&gt;AI-assisted CI is the obvious one. LLMs are already being used for code review, suggesting fixes for failing tests, and even generating test cases. GitHub Copilot can help write workflow files. The next step is AI that can diagnose build failures, suggest optimizations, and automatically fix common issues. We are not quite there yet, but the trajectory is clear.&lt;&#x2F;p&gt;
&lt;p&gt;Continuous fuzzing is becoming more practical. Fuzzing used to be something you ran occasionally on dedicated infrastructure. Now services like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;oss-fuzz&quot;&gt;OSS-Fuzz&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;clusterfuzz&#x2F;&quot;&gt;ClusterFuzz&lt;&#x2F;a&gt; make it possible to run fuzzing continuously as part of your CI pipeline. Every PR gets fuzzed, and any crashes are reported as test failures. This catches bugs that traditional testing misses.&lt;&#x2F;p&gt;
&lt;p&gt;Security scanning is shifting left, meaning it happens earlier in the development process rather than as a separate step before deployment. Tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;snyk.io&#x2F;&quot;&gt;Snyk&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aquasecurity&#x2F;trivy&quot;&gt;Trivy&lt;&#x2F;a&gt;, and GitHub’s own Dependabot scan for vulnerabilities in dependencies and container images as part of CI. The goal is to catch security issues before they make it to production.&lt;&#x2F;p&gt;
&lt;p&gt;The container image format itself is evolving. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;containerd&#x2F;stargz-snapshotter&quot;&gt;eStargz&lt;&#x2F;a&gt; enables lazy loading of container images, where only the parts of the image that are actually accessed get downloaded. This can dramatically speed up container startup times, especially for large images. The tradeoff is more complexity in the image format and runtime.&lt;&#x2F;p&gt;
&lt;p&gt;Compression is getting better too. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;facebook&#x2F;zstd&quot;&gt;Zstd&lt;&#x2F;a&gt; compression is faster and achieves better ratios than gzip for many workloads. BuildKit supports zstd for layer compression, and more registries are adding support. Smaller layers mean faster pushes and pulls.&lt;&#x2F;p&gt;
&lt;p&gt;The line between CI and development environment is blurring. Tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gitpod.io&#x2F;&quot;&gt;Gitpod&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;features&#x2F;codespaces&quot;&gt;GitHub Codespaces&lt;&#x2F;a&gt; give you a cloud development environment that is essentially the same as your CI environment. If your code works in Codespaces, it will work in CI, because they are running the same thing. This eliminates the “works on my machine” problem at its root.&lt;&#x2F;p&gt;
&lt;p&gt;Nix is gaining traction as a way to define reproducible build environments. Instead of hoping that your CI runner has the right versions of everything installed, you declare exactly what you need and Nix provides it. The appeal is that you can run the exact same build locally that runs in CI. No more debugging the difference between Ubuntu as set up in GitHub Actions and Arch as it is on your laptop. I wrote about &lt;a href=&quot;&#x2F;writes&#x2F;2024-07-31-nix&#x2F;&quot;&gt;getting started with Nix&lt;&#x2F;a&gt; a while back, and the more I use it the more I appreciate what it offers for CI.&lt;&#x2F;p&gt;
&lt;p&gt;The insight from the Hacker News discussion around these pain points was compelling. One commenter pointed out that strongly isolated systems like Nix and Bazel are amazing for giving no-fuss local reproducibility. Every CI platform is trying to seduce you into breaking things out into steps so that you can see their little visualizations of what is running in parallel. But that is the tail wagging the dog. The underlying build tool should be what is managing and ordering the build, not the GUI.&lt;&#x2F;p&gt;
&lt;p&gt;What people really want for next generation CI is a system that can get deep hooks into local-first tools. Do not make me define a bunch of steps for you to run. Instead talk to my build tool and just display for me what the build tool is doing. Show me the order of things it built, show me the individual logs of everything it did.&lt;&#x2F;p&gt;
&lt;p&gt;With Nix, your GitHub Actions workflow can be just a thin wrapper that calls &lt;code&gt;nix build&lt;&#x2F;code&gt; or &lt;code&gt;nix flake check&lt;&#x2F;code&gt;. The complexity lives in your Nix expressions, which you can run locally in an identical environment. Setting up a Nix build cache also means that any artifact built by your CI is instantly available locally, which can speed up some workflows a lot.&lt;&#x2F;p&gt;
&lt;p&gt;The security story is also better with Nix. Everything is pinned by default, that is the whole point of Nix. And Nix sandboxes builds, removing most network access. The cases where network access is allowed are made explicit. A dependency can request network access without your knowledge, but it is built without access to your code, making it irrelevant that it has that network access.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;garnix.io&#x2F;&quot;&gt;Garnix&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cachix.org&#x2F;&quot;&gt;Cachix&lt;&#x2F;a&gt; provide CI services built around Nix, with aggressive caching of build artifacts. The main downside has always been that you have to learn Nix, which has a steep learning curve. But increasingly there are tools to help with that, and the payoff in reproducibility and debuggability is real.&lt;&#x2F;p&gt;
&lt;p&gt;The fundamental challenge remains the same though. We want fast feedback on code changes, and we want confidence that what works in CI will work in production. The tools and techniques keep improving, but the goal is unchanged. The dream is a CI pipeline that runs in seconds, catches all the bugs, and never gives false positives. We are not there yet, but we are getting closer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-merge-queue-trap&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-merge-queue-trap&quot; aria-label=&quot;Anchor link for: the-merge-queue-trap&quot;&gt;The merge queue trap&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to keep your main branch clean, you need a merge queue. The idea is simple. Before a PR merges, it gets rebased onto the latest main and CI runs again. This ensures that what you tested is actually what gets merged, not some stale version that might conflict with changes that landed while your PR was in review.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub has a merge queue feature that handles this automatically. Sounds great until you try to set it up. The problem is that you often want CI to run twice. Once when the PR is opened to catch obvious issues and auto-fix trivial problems like formatting. And again inside the merge queue to verify the final merge. GitHub Actions makes this weirdly difficult.&lt;&#x2F;p&gt;
&lt;p&gt;The merge queue uses a separate event called &lt;code&gt;merge_group&lt;&#x2F;code&gt; that is distinct from &lt;code&gt;pull_request&lt;&#x2F;code&gt;. If you want the same checks to run in both contexts, you need to trigger on both events.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ull_request&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erge_group&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But here is where it gets confusing. If you have branch protection rules that require certain status checks to pass, those checks need to be reported for both the pull request and the merge group. The trick that people eventually discover after hours of debugging is to name the jobs identically in both phases. GitHub treats them as the same check, so they both need to succeed. Any other approach leads to either status checks being awaited before you can add something to the queue (so it never starts) or worse, things just get merged even if the merge queue job fails.&lt;&#x2F;p&gt;
&lt;p&gt;There is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;76655935&#x2F;when-does-a-github-workflow-trigger-for-merge-group-and-is-it-restricted-by-bran&#x2F;78030618#78030618&quot;&gt;Stack Overflow answer&lt;&#x2F;a&gt; that explains this after you have already spent a few hours trying to figure it out yourself. The documentation does not make this clear at all.&lt;&#x2F;p&gt;
&lt;p&gt;The other trap is that the &lt;code&gt;merge_group&lt;&#x2F;code&gt; event has completely different context variables than &lt;code&gt;pull_request&lt;&#x2F;code&gt;. Code that works fine in your PR workflow might break in the merge queue. The variables &lt;code&gt;github.base_ref&lt;&#x2F;code&gt; and &lt;code&gt;github.head_ref&lt;&#x2F;code&gt; are empty in merge group events. You need to use &lt;code&gt;github.event.merge_group.base_ref&lt;&#x2F;code&gt; and &lt;code&gt;github.event.merge_group.head_ref&lt;&#x2F;code&gt; instead. If your workflow does anything with branch names, you need conditional logic to handle both cases.&lt;&#x2F;p&gt;
&lt;p&gt;The debugging experience is also terrible. When a PR gets ejected from the queue, the UI shows a generic message like “removed from queue” without telling you which check failed. You have to manually inspect the temporary &lt;code&gt;gh-readonly-queue&#x2F;&lt;&#x2F;code&gt; branch to see what actually went wrong. And if you force push to a PR while it is in the queue, the queue does not notice. It keeps the stale green results for about 30 minutes before eventually ejecting the PR for having stale checks.&lt;&#x2F;p&gt;
&lt;p&gt;In April 2026, GitHub had a regression in merge queue operations that silently reverted previously merged code for about three and a half hours. The bug affected 658 repositories and over 2000 pull requests. It only happened with multi-PR merge queue groups using squash merge, and it was not detected by automated monitoring. Customers discovered it when their code disappeared. The fundamental contract of version control, that what you approve is what merges, was broken silently with clean green UI and no errors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-reliability-question&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-reliability-question&quot; aria-label=&quot;Anchor link for: the-reliability-question&quot;&gt;The reliability question&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Between May 2025 and April 2026, there were 57 tracked incidents for GitHub Actions, with 16 classified as major. In October 2025, macOS runners hit a 46 percent error rate for over 10 hours due to capacity constraints. Later that month, 29 percent of larger runner jobs failed due to database performance degradation. In February 2026, Azure provider issues caused a nearly four hour outage affecting Copilot, CodeQL, Dependabot, and Pages. An Actions outage can freeze an entire engineering workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Some high profile projects have left GitHub entirely because of reliability issues. The Zig programming language migrated to Codeberg in November 2025. Andrew Kelley, Zig’s lead developer, cited a bug in the runner’s &lt;code&gt;safe_sleep.sh&lt;&#x2F;code&gt; script that caused runners to hang indefinitely with 100 percent CPU usage. The bug was reported in April 2025 and not closed until December 2025. CI queues backed up so badly that master branch commits could not get checked.&lt;&#x2F;p&gt;
&lt;p&gt;Mitchell Hashimoto, GitHub user number 1299 who joined in February 2008, announced that Ghostty was leaving GitHub in April 2026. He kept a journal marking an X for every day an outage affected his work. Almost every day had an X. His conclusion was that GitHub is no longer a place for serious work if it blocks you out for hours per day, every day.&lt;&#x2F;p&gt;
&lt;p&gt;These are extreme cases, and most projects do not have the resources or motivation to migrate away from GitHub. But the reliability concerns are real. If your CI is critical to your development workflow, you need to think about what happens when it goes down. Do you have a way to test locally? Can you merge without CI in an emergency? Do you have alerts set up so you know when GitHub is having issues before you waste time debugging your own code?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-security-nightmare&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-security-nightmare&quot; aria-label=&quot;Anchor link for: the-security-nightmare&quot;&gt;The security nightmare&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In March 2025, someone compromised a popular GitHub Action called tj-actions&#x2F;changed-files. The attack was sophisticated. It started with a compromised personal access token from a SpotBugs maintainer, which was stolen through a malicious pull request that exploited the &lt;code&gt;pull_request_target&lt;&#x2F;code&gt; trigger. That token was used to gain write access to the SpotBugs repository, which led to compromising Reviewdog, which led to compromising tj-actions&#x2F;changed-files. The attackers retroactively modified multiple version tags to point to a malicious commit. The malicious version extracted secrets from the runner process memory and printed them to the workflow logs. Over 23,000 repositories were affected, including Coinbase.&lt;&#x2F;p&gt;
&lt;p&gt;The attack was active for about a day before it was discovered. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;semgrep.dev&#x2F;blog&#x2F;2025&#x2F;popular-github-action-tj-actionschanged-files-is-compromised&#x2F;&quot;&gt;Semgrep published a detailed analysis&lt;&#x2F;a&gt; recommending that affected teams stop using the action immediately, remove it from all branches not just main, and rotate any secrets that may have been exposed. The gist that was used to retrieve credentials was eventually removed and returns a 404 now, but the damage was done.&lt;&#x2F;p&gt;
&lt;p&gt;The response from the security community was predictable. Pin your dependencies to a hash. Except almost nobody does that because it is tedious and makes updates harder. The real lesson is that the GitHub Actions security model is complicated enough that even experienced teams get it wrong.&lt;&#x2F;p&gt;
&lt;p&gt;There is a default token called &lt;code&gt;GITHUB_TOKEN&lt;&#x2F;code&gt; that every workflow gets. The permissions it has depend on your repository settings, your workflow file, and whether the workflow was triggered by a fork. Prior to February 2023, the default was read-write access to everything. Now the recommendation is to set it to read-only by default and explicitly grant permissions in your workflow file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ermissions&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontents&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ull-requests&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; w&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rite&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem is that there are many permissions and it is not always clear what each one protects. And your workflow permissions do not just depend on what you set. They depend on how the workflow was triggered. The &lt;code&gt;pull_request&lt;&#x2F;code&gt; trigger runs in the context of the fork with limited permissions. The &lt;code&gt;pull_request_target&lt;&#x2F;code&gt; trigger runs in the context of the base repository with full access to secrets. This is useful for things like labeling PRs from external contributors, but it is also a massive footgun if you check out and run code from the PR.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;OWASP&#x2F;CheatSheetSeries&#x2F;blob&#x2F;master&#x2F;cheatsheets&#x2F;GitHub_Actions_Security_Cheat_Sheet.md&quot;&gt;OWASP GitHub Actions Security Cheat Sheet&lt;&#x2F;a&gt; recommends setting &lt;code&gt;permissions: {}&lt;&#x2F;code&gt; at the workflow level to disable all permissions by default, then granting only what each job needs. This is good advice but it means you need to understand what permissions each action you use actually requires.&lt;&#x2F;p&gt;
&lt;p&gt;There is a critical gotcha with the permissions key that trips up developers constantly. When you specify any permission, all unspecified permissions default to none. So if you add &lt;code&gt;contents: write&lt;&#x2F;code&gt; to push some files, you suddenly lose &lt;code&gt;pull-requests: read&lt;&#x2F;code&gt; and your workflow can no longer comment on PRs. This is documented but buried, and it causes mysterious permission denied errors that are hard to diagnose.&lt;&#x2F;p&gt;
&lt;p&gt;Self-hosted runners add another layer of complexity. GitHub recommends only using them with private repositories because forks of public repositories can potentially run dangerous code on your runner. There is a setting to require approval for workflows from external contributors, but the documentation does not clearly state whether this makes self-hosted runners safe for public repositories. The answer is probably yes, but probably is not good enough for security.&lt;&#x2F;p&gt;
&lt;p&gt;One analysis found that 91 percent of PyPI packages that use third-party actions reference at least one by mutable tag, and two thirds have no permissions block on at least one workflow. The supply chain attack surface is enormous, and most projects are not taking basic precautions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;docker-and-github-actions-do-not-mix-well&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#docker-and-github-actions-do-not-mix-well&quot; aria-label=&quot;Anchor link for: docker-and-github-actions-do-not-mix-well&quot;&gt;Docker and GitHub Actions do not mix well&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GitHub lets you run jobs inside a container. This sounds great because you can prepackage all your dependencies into a dev container instead of installing them on every run. In practice, it is a minefield.&lt;&#x2F;p&gt;
&lt;p&gt;File permissions break constantly. The container might build files as one user, but the GitHub runner uses a different uid and gid. So the runner might not be able to access files created by the container, or vice versa. You end up sprinkling &lt;code&gt;chown&lt;&#x2F;code&gt; commands everywhere or running everything as root, which defeats the purpose of having user isolation.&lt;&#x2F;p&gt;
&lt;p&gt;Runner version 2.332.0 in early 2026 introduced stricter ownership checks that broke many container workflows. The runner now explicitly verifies that the service user can write to &lt;code&gt;GITHUB_ENV&lt;&#x2F;code&gt; and the workspace directory inside container jobs. You get errors like “EACCES: permission denied” on the runner file command directories, or git complaining about dubious ownership in the repository. The fix usually involves matching the container user to the host runner user, which is not always straightforward.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; G&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;et host UID&#x2F;GID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;UID=$(id -u)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;GID=$(id -g)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tart containers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ocker-compose up -d --user &amp;quot;$UID:$GID&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;$HOME&lt;&#x2F;code&gt; directory moves. Your dev container might install tools into &lt;code&gt;&#x2F;home&#x2F;ubuntu&lt;&#x2F;code&gt;, but inside GitHub Actions it is suddenly &lt;code&gt;&#x2F;github&#x2F;home&lt;&#x2F;code&gt;. Tools that rely on files in &lt;code&gt;$HOME&lt;&#x2F;code&gt; stop working because they cannot find their config files or caches.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a path resolution problem that causes cache misses. The &lt;code&gt;github.workspace&lt;&#x2F;code&gt; variable resolves to &lt;code&gt;&#x2F;__w&lt;&#x2F;code&gt; inside containers but maps to different absolute paths on the host. The cache action includes the file path in its versioning, so a cache created by a job running without a container cannot be restored by a job running in a container, even if the contents are identical.&lt;&#x2F;p&gt;
&lt;p&gt;Any action that interacts with the host system might break when running in a container. For example, some teams use sticky disk actions to mount NVMe drives for caching because GitHub’s 10GB cache limit is not enough for large Rust projects. These actions need to interact with the host filesystem and block devices, which does not work inside a container without special configuration. You need to run the container in privileged mode and pass through specific environment variables.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;mage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y-dev-container:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ptions&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; --&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;privileged&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    V&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;M_ID&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ env.VM_ID }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    B&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;LACKSMITH_STICKYDISK_TOKEN&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ env.BLACKSMITH_STICKYDISK_TOKEN }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;container&lt;&#x2F;code&gt; field itself has weird limitations. You cannot override the entrypoint. You cannot run some steps inside a container and others outside. If you need that flexibility, you have to use &lt;code&gt;docker run&lt;&#x2F;code&gt; manually in your steps, which defeats the convenience of the &lt;code&gt;container&lt;&#x2F;code&gt; field.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yaml-is-not-a-programming-language&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#yaml-is-not-a-programming-language&quot; aria-label=&quot;Anchor link for: yaml-is-not-a-programming-language&quot;&gt;YAML is not a programming language&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;All of this logic ends up written in YAML, which gets complicated quickly. You are bound to make mistakes, and the feedback loop is terrible. You cannot really test workflows locally. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nektos&#x2F;act&quot;&gt;act&lt;&#x2F;a&gt; tool tries to run GitHub Actions locally but it only supports a subset of features. Complex workflows with matrix builds, reusable workflows, or container jobs often do not work.&lt;&#x2F;p&gt;
&lt;p&gt;The silent failures are the worst part. A typo like &lt;code&gt;branch:&lt;&#x2F;code&gt; instead of &lt;code&gt;branches:&lt;&#x2F;code&gt; causes your workflow to silently not trigger. YAML is case sensitive, so &lt;code&gt;Shell:&lt;&#x2F;code&gt; instead of &lt;code&gt;shell:&lt;&#x2F;code&gt; or &lt;code&gt;default:&lt;&#x2F;code&gt; instead of &lt;code&gt;defaults:&lt;&#x2F;code&gt; creates valid YAML that does nothing. There is no error, no warning, just a workflow that does not run when you expect it to.&lt;&#x2F;p&gt;
&lt;p&gt;YAML scalar blocks have their own gotcha. If you have a multiline bash script inside a &lt;code&gt;|&lt;&#x2F;code&gt; block and any line starts at column zero, it terminates the block. Your bash script gets silently truncated. Forty lines of bash inside YAML means two syntaxes in the same file where every space has a different meaning depending on context.&lt;&#x2F;p&gt;
&lt;p&gt;The best debugging strategy I have found is to create a test repository and do &lt;code&gt;git commit -a -m &quot;wip&quot; &amp;amp;&amp;amp; git push&lt;&#x2F;code&gt; until CI works as expected. This is slow and tedious but at least you get real feedback.&lt;&#x2F;p&gt;
&lt;p&gt;One pattern that helps is keeping individual workflows small and having them push artifacts at the end. Subsequent workflows download the artifacts and reuse them instead of rebuilding everything. This lets you test workflows in isolation because you can download artifacts from a previous run.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nvoke-build-rust&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild Rust&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;.github&#x2F;workflows&#x2F;build-rust.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nvoke-tests-unit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nit Tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eeds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nvoke-build-rust&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;.github&#x2F;workflows&#x2F;test-unit.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nvoke-tests-integration&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ntegration Tests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eeds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nvoke-build-rust&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;.github&#x2F;workflows&#x2F;test-integration.yml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ecrets&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nherit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice the &lt;code&gt;secrets: inherit&lt;&#x2F;code&gt; on some jobs. This is another gotcha that takes too long to figure out. When you call a workflow from another workflow, secrets are not shared by default. Your entire CI pipeline works when you run steps individually but fails when you run the whole thing because the called workflow cannot access the secrets it needs.&lt;&#x2F;p&gt;
&lt;p&gt;There are many more gotchas like this. Environment variables behave differently in different contexts. Expressions have their own syntax that is almost but not quite like JavaScript. Conditionals can be tricky because &lt;code&gt;if: failure()&lt;&#x2F;code&gt; runs when a previous step failed, but &lt;code&gt;if: always()&lt;&#x2F;code&gt; runs even when the workflow was cancelled. The documentation is extensive but scattered, and you often only find the answer after you have already hit the problem.&lt;&#x2F;p&gt;
&lt;p&gt;The advice that keeps coming up from people who have dealt with CI for years is to write as much CI logic as possible in your own code. It does not really matter what you use, shell scripts, make, just, whatever, as long as it is proper maintainable code that you can run locally. Invest time so that your pipelines can run locally on a developer machine as much as possible, otherwise testing and debugging pipelines becomes a nightmare. Avoid YAML as much as possible. And always use your own runners if you can, on premise if possible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-control-plane-is-no-longer-free&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-control-plane-is-no-longer-free&quot; aria-label=&quot;Anchor link for: the-control-plane-is-no-longer-free&quot;&gt;The control plane is no longer free&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In December 2025, GitHub announced a significant pricing change. Previously, if you used GitHub Actions but ran jobs on your own infrastructure or a third party service, you paid nothing to GitHub for those minutes. The control plane was free. You only paid for compute.&lt;&#x2F;p&gt;
&lt;p&gt;That changed with the introduction of a 0.002 dollar per minute platform fee on all GitHub Actions usage. This fee applies regardless of where your jobs run. CI costs now have two components. Compute costs go to whoever runs your runners. And a flat GitHub platform fee gets charged per minute of Actions usage. The changes went into effect on March 1st 2026.&lt;&#x2F;p&gt;
&lt;p&gt;The reasoning is straightforward. GitHub Actions has always had a graduation churn problem. As companies grow, their CI workloads become larger and more expensive. At a certain scale, GitHub hosted runners become both slow and costly, pushing teams to self host or move to third party runners. Until now, that shift meant companies could continue using the GitHub Actions control plane while paying GitHub nothing for CI execution. The new platform fee changes that. It directly monetizes the control plane and establishes a floor on what GitHub earns from CI regardless of where jobs run.&lt;&#x2F;p&gt;
&lt;p&gt;At the same time, GitHub reduced the price of hosted runners. This is not accidental. Lower hosted runner prices make GitHub hosted runners more attractive, while the platform fee introduces a new unavoidable cost for self hosting. GitHub is trading lower margin compute revenue for higher margin platform revenue.&lt;&#x2F;p&gt;
&lt;p&gt;The practical implication is that self hosting no longer lets you avoid paying GitHub entirely. The primary variable you can still control is how many minutes your CI jobs consume. This makes CI performance and cost tightly coupled. Faster builds mean lower platform fees. The remaining lever is reducing CI time and total Actions usage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;debugging-without-access&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#debugging-without-access&quot; aria-label=&quot;Anchor link for: debugging-without-access&quot;&gt;Debugging without access&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes debugging a failing CI job is like being a mechanic looking at a car that will not start. You poke and prod from the outside, but until you have popped the hood, all you can do is guess. A job fails. Is a flaky test to blame? Did the VM run out of memory? Or is it something else entirely? Without real access, you are stuck troubleshooting in the dark, relying on logs at best.&lt;&#x2F;p&gt;
&lt;p&gt;Some third party runner services have built SSH access into their platforms. The idea is to let you connect directly to a running CI job and poke around. This requires solving three problems. Network tunneling to route external connections to the right VM. DNS registration so you can connect with a human readable hostname instead of an IP and port. And SSH key management to ensure only the right people can access the VM.&lt;&#x2F;p&gt;
&lt;p&gt;The network tunneling uses iptables rules to redirect incoming connections to a specific host port and rewrite the destination to the VM’s internal IP and SSH port. The DNS challenge is that DNS propagation takes minutes, but CI VMs are short lived. The solution is to run a custom DNS service that registers hostnames immediately when VMs are created, making them discoverable worldwide without waiting for propagation.&lt;&#x2F;p&gt;
&lt;p&gt;The result is that you can SSH into a running job with something like &lt;code&gt;ssh runner@vm-abc123.vm.example.sh&lt;&#x2F;code&gt; and poke around while the job is still running. When the job completes, there is a grace period of a few minutes where you can continue debugging before the VM gets torn down. GitHub has an undocumented 5 minute timeout for waiting on the job completion hook, so the grace period is usually just under 5 minutes.&lt;&#x2F;p&gt;
&lt;p&gt;This kind of access is not available on GitHub hosted runners. You can add a step that pauses the workflow and waits for you to SSH in using something like tmate, but it is clunky and requires modifying your workflow. Native SSH access that just works without any workflow changes is a feature that only third party services offer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-push-wait-guess-loop&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-push-wait-guess-loop&quot; aria-label=&quot;Anchor link for: the-push-wait-guess-loop&quot;&gt;The push wait guess loop&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Debugging CI feels like mailing a car mechanic instructions for a single turn of a wrench, waiting three days, and getting mailed back a polaroid of a burning car with the caption exit code 1.&lt;&#x2F;p&gt;
&lt;p&gt;The old CI debugging experience goes like this. You edit a workflow file, hope you have not committed some ancient YAML war crime, commit, push, wait, and then squint at the logs to parse the useful from the haystack. Was I in the right working directory? Did checkout happen the way I thought? Did the file actually exist? Did the variable get set in this context? Did the artifact land where I assumed it would? Who knows. Certainly not me.&lt;&#x2F;p&gt;
&lt;p&gt;If the failing step sits at the end of a long job, even better. Now you get to wait 15 minutes to learn that your latest guess was also wrong. That old loop is more hope filled finger crossing than debugging.&lt;&#x2F;p&gt;
&lt;p&gt;The best debugging strategy most people land on is to create a test repository and do &lt;code&gt;git commit -a -m &quot;wip&quot; &amp;amp;&amp;amp; git push&lt;&#x2F;code&gt; until CI works as expected. This is slow and tedious but at least you get real feedback. Your git history becomes a graveyard of commits like fix typo, fix typo again, and fix asdfasdl.&lt;&#x2F;p&gt;
&lt;p&gt;Some third party CI services have started to change this. The idea is to turn CI from a remote black box into a local closed loop you can actually drive from your IDE or terminal. You can run a workflow against your current local diff without committing. You can scope it down to one job. You can inspect status and logs. You can stop after a specific step. You can SSH into the actual machine. You can fix the problem locally and rerun until it passes.&lt;&#x2F;p&gt;
&lt;p&gt;The workflow becomes run, inspect status, read logs, stop at the interesting step, SSH in, check reality, fix locally, rerun, green. All from the comfort of your terminal. You do not have to live in the land of guesses, hopes, and finger crosses because you can almost completely control the loop while having access to all the context and tools you need to fix and iterate.&lt;&#x2F;p&gt;
&lt;p&gt;Half the pain of CI debugging is not even the bug. It is the tab olympics. IDE, terminal, browser, logs page, back to code, back to the run, back to the logs because the UI forgot where you were. By the time you have enough signal to form a decent hypothesis, you are already cognitively cooked.&lt;&#x2F;p&gt;
&lt;p&gt;Once CI debugging becomes a loop of CLI commands, it becomes something an agent can handle. The agent runs the same loop you would. Read the logs. Rerun the job with a stop after a specific step. SSH into the runner and check reality with pwd and ls and whatever else the moment requires. Apply a local fix, rerun, and keep going until the job turns green. The agent has something you lack during a 6pm debugging session. Patience. It does not get fried or bored. It just methodically checks reality against the YAML until they match.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bottleneck-has-shifted&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-bottleneck-has-shifted&quot; aria-label=&quot;Anchor link for: the-bottleneck-has-shifted&quot;&gt;The bottleneck has shifted&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For decades, the biggest bottleneck to innovation was writing code. But that is no longer true. Code and ideas can now iterate as fast as you can articulate them to an AI agent with a powerful model. Iteration can be done in seconds instead of hours. A new generation of tools, services, and products are being imagined faster than ever.&lt;&#x2F;p&gt;
&lt;p&gt;The bottleneck has shifted from writing code to integrating it.&lt;&#x2F;p&gt;
&lt;p&gt;When LLMs first became available to the public, the developer ecosystem was quick to experiment with them. We saw folks generate code from prompts. It kind of worked and it was neat. But it was also a bit of a mess. The code was often buggy and the quality was often questionable. But it was a start. We started seeing their potential, but we did not really trust them.&lt;&#x2F;p&gt;
&lt;p&gt;So we figured out ways to integrate them into our existing workflows. The idea of spinning up agents via things like GitHub Actions became a thing. We quickly started seeing AI agents being bolted on to our existing workflows for code reviews, test generation, and more. In essence, we took this new experimental capability and bolted it on to our existing human centric workflows.&lt;&#x2F;p&gt;
&lt;p&gt;Then things changed. It felt like overnight, but it was steady improvements in model capabilities every couple of weeks. Models got better at understanding code, better at generating code, better at understanding context, better at understanding codebases. We shifted from a world where the agents and models were experimental and hard to trust to one where they are reliable, productive, and better than humans at many tasks.&lt;&#x2F;p&gt;
&lt;p&gt;With that shift, a new traffic jam formed in our human centric workflows. Engineering teams operating with agents are now seeing the downstream effects of their newfound productivity. Pull requests pile up faster than humans can review them. CI queues grow because builds and tests are taking too long to run. Merge conflicts multiply as more changes flow simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;Repurposing our existing workflow that focused on engineers in the middle of everything is now at the root of the bottleneck. Bolting AI into our existing workflows worked okay initially. This worked when writing code was the slow part. When a developer spent days on a feature, 20 minutes of CI was not the constraint. When you can generate a feature in 20 minutes, a 20 minute CI pipeline is unacceptable.&lt;&#x2F;p&gt;
&lt;p&gt;The human centric workflows we built assume developers work at a measured, deliberate pace. Code review happens asynchronously. CI runs are expensive. Integration happens infrequently because changes are large and risky. None of these hold anymore. AI agents produce working code in minutes, attempt dozens of approaches simultaneously, and generate code around the clock. But they are forced into collaboration patterns designed for humans working business hours on carefully crafted changes.&lt;&#x2F;p&gt;
&lt;p&gt;Real time feedback loops are what empower software engineering at scale. We need tests to run on every commit, merge conflicts to self resolve automatically, context about how the code was developed should live right next to the code, and builds should be near instant. All of this should be seamless for both humans and agents.&lt;&#x2F;p&gt;
&lt;p&gt;It is not about a human in the loop anymore. It is about humans orchestrating work being done at scale, with engineers deciding what good versus bad is, what to iterate on, what ideas to explore, and what to ship next.&lt;&#x2F;p&gt;
&lt;p&gt;Teams with 60 second builds make fundamentally different decisions than teams with 40 minute builds. They try more things. They validate assumptions faster. They catch issues earlier. Speed does not trade off with quality. Speed enables quality.&lt;&#x2F;p&gt;
&lt;p&gt;Every team adopting AI coding tools will hit this bottleneck. Some already have. But we are likely only at 1 to 2 percent adoption of AI coding tools. As adoption increases, this bottleneck becomes the most pronounced barrier to break down. Teams that figure out how to bust through it will have a massive competitive advantage. They will operate with a new paradigm, where agents have everything they need to go from engineers ideas to running in production as quickly and autonomously as possible. They will run circles around their competitors who do not have this new paradigm.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-ci-needs-to-be-for-agents&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-ci-needs-to-be-for-agents&quot; aria-label=&quot;Anchor link for: what-ci-needs-to-be-for-agents&quot;&gt;What CI needs to be for agents&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The CI systems we have today are built around specific assumptions. A developer writes some code, pushes it to a branch, opens a pull request, and waits. Most engineers context switch to something else while waiting for CI to finish. The traditional processes measure feedback loops in minutes or tens of minutes. It was not great but it was fine enough.&lt;&#x2F;p&gt;
&lt;p&gt;With agents writing code, that assumption collapses. An agent can write code in seconds, commit it, monitor CI, read the results, watch for regressions in the logs, detect issues, fix them, and push again in a loop much faster than any CI system was designed to support. The agent is not doing something else while CI runs. It is blocked.&lt;&#x2F;p&gt;
&lt;p&gt;Today CI systems force humans back into the loop. To help the agent context switch to something else while waiting for CI. To paste errors from CI back into the agent and say fix it. To help the agent get logs about what regressed. Every time an agent has to push code and wait for CI or have a human help it understand its results, you have added friction to a process that is supposed to be autonomous.&lt;&#x2F;p&gt;
&lt;p&gt;CI is now in the critical path in a way it never quite was before.&lt;&#x2F;p&gt;
&lt;p&gt;If you think about what makes CI painful specifically for agentic workflows, a few things stand out. First is targeted reruns instead of full pipeline reruns. Nothing is more annoying than trying to debug one step inside of a fifteen step CI workflow. That drives engineers nuts. But it actively blocks agents from finishing their work. When an agent is finishing a feature, waiting for a 15 minute pipeline to finish while validating a 3 line fix inside of a fifteen step workflow is genuinely wasteful in terms of time and tokens. Agents need to be able to rerun a single job inside of a workflow, not restart from scratch every time.&lt;&#x2F;p&gt;
&lt;p&gt;Second is running real CI on local patches. Agents and engineers today have to commit and pray to learn if their debugging hypothesis is correct. That is the worst possible inner loop. Write a change, commit it, push it up, wait 5 minutes, get a result, it is broken, revert, try again. CI should be able to be invoked with local file changes from the agent writing the code. The agent writes a change, validates it, and only commits once it knows it works. No more pushing broken commits just to find out they are broken.&lt;&#x2F;p&gt;
&lt;p&gt;Third is all context behind an API. Most CI systems were designed for humans clicking through dashboards. Their API is a bolted on concept, not something designed to be the primary interface. Agents do not click through dashboards. They need to trigger runs, poll status, retrieve logs, and make decisions programmatically. If the API is not there to give agents context, you are forcing them into hacky workarounds.&lt;&#x2F;p&gt;
&lt;p&gt;Fourth is speed and orchestration at scale. A single engineer can be operating tens of agents simultaneously. Several agents, several branches, all needing CI at the same time. The latency, queueing, and run time of your CI pipelines and their backing providers matter a lot more when you have 20 agents all trying to validate changes at once.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub is aware of this shift. In February 2026, they launched &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.blog&#x2F;ai-and-ml&#x2F;automate-repository-tasks-with-github-agentic-workflows&#x2F;&quot;&gt;Agentic Workflows&lt;&#x2F;a&gt; in technical preview. The idea is what they call Continuous AI, the integration of AI into the software development lifecycle. You define intent in Markdown with YAML frontmatter, compile it into a hardened GitHub Actions lock file, and let AI agents handle jobs that require judgment. Issue triage, code review, documentation drift detection, CI failure investigation.&lt;&#x2F;p&gt;
&lt;p&gt;The architecture is interesting. When you run &lt;code&gt;gh aw compile&lt;&#x2F;code&gt;, it generates a lock file that is a full GitHub Actions workflow with multiple jobs, trust boundaries, and permission gates. The Markdown stays the human readable source of truth. The lock file is the security hardened executable. When the agent wants to add a label, post a comment, or create a PR, it does not do it directly. Those write operations execute in separate, permission controlled jobs after the agent finishes. Each safe output has hard limits like max 3 labels or max 1 comment, plus sanitization and policy checks.&lt;&#x2F;p&gt;
&lt;p&gt;This is not replacing your build test deploy pipeline. It is adding a new layer on top that handles the judgment heavy work that was too messy to automate before. Agentic workflows run on GitHub Actions because that is where GitHub provides the necessary infrastructure for permissions, logging, auditing, sandboxed execution, and rich repository context.&lt;&#x2F;p&gt;
&lt;p&gt;The supported engines include GitHub Copilot, Claude Code, OpenAI Codex, and custom OpenAI compatible engines. You can have an agent take a bug report, generate a fix, get it reviewed, and deploy it to production with a human in the loop at the right moment. Not fully autonomous, not fully manual. Just the right amount of automation for shipping with confidence.&lt;&#x2F;p&gt;
&lt;p&gt;But this is still early days. The fundamental problem remains that CI was designed for humans. The queueing behavior, cold start latency, and per job runtime of your CI system matter a lot more when a team of ten humans pushing thirty commits a day becomes a single engineer running twenty agents simultaneously, each on its own branch, each needing CI to validate its work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-buildkite-exodus&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-buildkite-exodus&quot; aria-label=&quot;Anchor link for: the-buildkite-exodus&quot;&gt;The Buildkite exodus&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;At some point, usually around 75 engineers, teams start looking for alternatives. The pattern is consistent. CI costs grow almost quadratically with the number of engineers because the test suite grows and more engineers run it more often. GitHub Actions starts feeling slow and unreliable. The merge queue breaks in mysterious ways. And then someone mentions Buildkite.&lt;&#x2F;p&gt;
&lt;p&gt;The reliability difference is stark. One engineer on Twitter put it bluntly. At his last job they self hosted GitLab and used its CI features. In nearly five years he did not remember a single outage. In the year and change he had been back on GitHub, random features or more commonly GitHub Actions had been down repeatedly. Looking at the numbers, GitHub Actions had 57 outages tracked between May 2025 and April 2026, making it the most affected GitHub service. That works out to roughly one significant disruption per week. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.buildkitestatus.com&#x2F;&quot;&gt;Buildkite status page&lt;&#x2F;a&gt; tells a different story. Their web service shows 100 percent uptime over 90 days. Agent API at 99.98 percent. REST API at 100 percent. Job queue at 99.94 percent. The architectural difference is that Buildkite decouples the control plane from execution. Builds run on your infrastructure, so you are not affected by multi tenant contention or GitHub’s infrastructure failures.&lt;&#x2F;p&gt;
&lt;p&gt;Self hosting is where Buildkite really shines compared to GitHub Actions. GitHub offers the Actions Runner Controller, a Kubernetes controller for self hosted runners. Setting it up involves creating an EKS cluster, installing ARC using its Helm chart, configuring GitHub App authentication and Kubernetes secrets, setting up autoscaling based on queue length, configuring logging and monitoring with CloudWatch or Prometheus or Grafana, and setting up IAM roles and security groups. It requires Kubernetes experience and comes with all the operational overhead of Docker in Docker and dealing with GitHub’s unreliable webhook delivery. ARC also runs jobs in containers rather than full virtual machines, which breaks compatibility with some workflows.&lt;&#x2F;p&gt;
&lt;p&gt;Buildkite makes self hosting much easier with their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;buildkite&#x2F;elastic-ci-stack-for-aws&quot;&gt;Elastic CI Stack for AWS&lt;&#x2F;a&gt;, a CloudFormation stack that spins up a Buildkite agent fleet on AWS. It is almost a one click solution because most settings are preconfigured. Since their agents run directly on EC2 instances rather than in Kubernetes pods, it is a much simpler solution. The stack handles autoscaling, instance storage, git mirrors, and agent lifecycle automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the actual configuration in their stack, you can see how much thought went into the details. The launch script sets up git mirrors by default when enabled, mounting them to instance storage for performance. The install script handles everything from agent token retrieval from SSM to setting up the build path on ephemeral storage. There is even a &lt;code&gt;BuildkiteAgentEnableGitMirrors&lt;&#x2F;code&gt; parameter that configures the agent to maintain local git mirrors, which makes cloning substantially faster because it uses direct disk access rather than hitting the network.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;ParameterKey&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;BuildkiteAgentEnableGitMirrors&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;ParameterValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Buildkite also has features that GitHub Actions simply lacks. Test analytics gives you a detailed overview of your test suite’s health, showing which tests are passing, failing, and flaky. It ranks tests by least reliable and slowest. They have test collectors for popular languages and frameworks that send results to Buildkite for visualization. GitHub Actions has nothing like this. Most teams using GitHub Actions end up paying for third party observability tools to get similar insights.&lt;&#x2F;p&gt;
&lt;p&gt;Automatic retries are a first class primitive in Buildkite’s DSL. You can specify conditions under which to rerun and how many times a step can be rerun. This is useful because you might want to retry during a failing test but not during a deployment.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;abel&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Tests&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;tests.sh&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etry&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;utomatic&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;xit_status&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;xit_status&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;xit_status&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;          l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;GitHub Actions does not have retries built into its DSL. There are third party actions that let you retry a step when it fails, but since they are not first party they are not as well known or widely adopted. And there is no dashboard to visualize how often a given step was retried.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;buildkite&#x2F;buildkite-agent-metrics&quot;&gt;Buildkite agent metrics&lt;&#x2F;a&gt; project makes it easy to get visibility into agent health. You can see queue times, job durations, and agent utilization. This kind of observability is essential when you are running your own infrastructure and need to know when to scale up or down.&lt;&#x2F;p&gt;
&lt;p&gt;For regulated industries like healthcare or finance, the security model matters. With Buildkite, agents run entirely in your VPC. Code and secrets never leave your network. With GitHub Actions, even with self hosted runners, the control plane is on github.com. Some auditors do not accept this for HIPAA or PCI compliance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-your-ci-job-talking-to&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-your-ci-job-talking-to&quot; aria-label=&quot;Anchor link for: what-is-your-ci-job-talking-to&quot;&gt;What is your CI job talking to&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One thing that surprised me when I started digging into CI performance is how much time builds spend waiting on the network. Pulling images, resolving and downloading dependencies, hitting caches, cloning repos. When a build is slow, the answer is very often hiding in a network flow nobody knew existed. The registry that is not cached. The dependency fetched from the other side of the world. The test suite quietly downloading a browser binary on every run.&lt;&#x2F;p&gt;
&lt;p&gt;Knowing exactly what every job talks to is also the basis for security. When a dependency turns malicious, you want to know which jobs were affected. But getting this visibility is hard because the workload inside the VM is untrusted. A CI job runs arbitrary code and that code can become root inside the guest. Anything living in the guest is within the blast radius of the thing you are trying to observe.&lt;&#x2F;p&gt;
&lt;p&gt;Some CI providers are starting to build network observability into their platforms. The approach is to capture a complete and queryable record of all outbound network traffic, attributed to the domain name per job and even per step. This is done without a man in the middle proxy that would break certificate pinning, without adding measurable latency, and without anything inside the guest that the workload could see or reconfigure.&lt;&#x2F;p&gt;
&lt;p&gt;The key insight is that everything meaningful is a name but the kernel deals in IPs. Knowing a job sent 4 MB to some IP address is close to useless. Knowing it went to github.com on port 443 is the whole point. The solution is to own DNS with a host side proxy. Every DNS query from the VM gets intercepted and forwarded, and the proxy records which names resolved to which IPs. Then eBPF programs attached to the VM’s network interface count bytes per destination, and the DNS records let you attribute those bytes back to domain names.&lt;&#x2F;p&gt;
&lt;p&gt;This kind of observability is not available in GitHub Actions. You can see that your build took 10 minutes but you cannot see that 3 minutes of that was waiting on a slow registry pull or that your test suite downloaded 500 MB of browser binaries on every run. The information exists somewhere in the system but it is not exposed to you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-hidden-costs-of-self-hosting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-hidden-costs-of-self-hosting&quot; aria-label=&quot;Anchor link for: the-hidden-costs-of-self-hosting&quot;&gt;The hidden costs of self hosting&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Managing your own CI infrastructure sounds appealing in theory. You get complete control, can optimize for your specific workloads, and avoid vendor lock in. But after months of wrestling with self hosted GitHub runners, many DevOps teams learn the hard way that the operational overhead can seriously outweigh the benefits.&lt;&#x2F;p&gt;
&lt;p&gt;AMI maintenance becomes a substantial time sink. Security compliance typically requires updating AMIs at least monthly, and that time patching, testing, and rolling out updates adds up. What started as just keeping things current can turn into a part time job for your platform team. AWS now provides a full Neptune graph database solution just for tracking AMI relationships, which gives you a sense of how complex this governance has become. If you need that level of lineage tracking, you are building significant infrastructure just to manage your CI infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;Rollouts with non ephemeral runners are scary. One bad rollout can take down an entire CI pipeline, and rollbacks are not always clean because persistent state has already been modified. Failures become difficult to diagnose because rerunning the same commit does not recreate the same conditions. A job may succeed or fail based on artifacts left by a previous unrelated job. GitLab’s security guidance explicitly warns that self managed CI jobs create remote code execution risk, and this risk sharpens when non ephemeral runners are shared across projects.&lt;&#x2F;p&gt;
&lt;p&gt;The GitHub Runner APIs have documented quirks that bite teams regularly. The REST API can report &lt;code&gt;busy: false&lt;&#x2F;code&gt; while a runner is actively executing a job. The broker knows the runner is busy but the REST API does not. Autoscalers that rely on the REST API will terminate instances mid job. One team reported losing 21 containers in an hour during a webhook driven spawn burst because the registration token endpoint returned 502 errors in bursts. Runners can get stuck in an active state where jobs remain queued for hours and only a manual restart resolves it. The terraform-aws-github-runner module, which is the recommended autoscaling solution, is directly affected by these bugs. The workaround is switching to strictly ephemeral runners.&lt;&#x2F;p&gt;
&lt;p&gt;Spot instances might save money but they can cause bad developer experience. Sure you might lower your bill, but try explaining to your engineering team why their builds are randomly failing because AWS reclaimed the instance mid job. One engineering team reported that moving to spot increased their median and average build times by about 33 percent, which was a deal breaker they had to fix immediately. The developer productivity cost has to be judged against the infrastructure savings. Making spot work requires checkpointing so jobs can pick up where predecessors died, persistent caching so adding more runners does not just multiply cold build costs, intelligent retries that detect interruption signals and auto requeue on fresh nodes, and hybrid infrastructure that uses on demand for release builds and spot for unit tests.&lt;&#x2F;p&gt;
&lt;p&gt;Scaling discussions consume engineering time. Getting scaling curves right is complex. Too conservative and you are wasting money on idle capacity. Too aggressive and developers wait for runners during peak times. It is surprisingly easy to spend countless hours in meetings debating scaling parameters instead of shipping features. The parameters you need to tune include idle count, idle time, capacity per instance, max builds before instance replacement, and time based scaling for business hours versus weekends. The goal is zero wait time for developers without paying for idle capacity, but finding that balance is ongoing work.&lt;&#x2F;p&gt;
&lt;p&gt;AWS Savings Plans can secure significant discounts but they also create financial lock in. You might end up paying for weekend capacity you do not actually use. Unused commitment in any hour is wasted. It cannot be saved for a busier hour, cannot offset earlier on demand charges, cannot become an account credit, and is not refunded. A big financial commitment to one vendor can make it harder to experiment with other solutions even when your current setup is not working well. The guidance is to commit at 70 to 80 percent of your minimum 60 day baseline, not average or peak, and to layer commitments in smaller incremental blocks rather than one large multi year plan.&lt;&#x2F;p&gt;
&lt;p&gt;The egress cost blindside is real. Without careful network architecture, data transfer costs can easily hit six figures annually. Every DevOps team has a story of learning this the expensive way when a surprisingly large AWS bill shows up. NAT Gateway charges 0.045 dollars per GB on every byte that crosses it, on top of hourly gateway costs and standard internet egress. One team discovered their CI pipeline was running 340 times per day instead of 12, with each run pulling a 400MB Docker image, 200MB of npm packages, and pushing 400MB to ECR. That added up to 61TB through NAT over 180 days, resulting in over 10000 dollars per month in NAT Gateway charges alone. The fixes include using free VPC Gateway Endpoints for S3 and DynamoDB, Interface Endpoints for ECR and CloudWatch and Secrets Manager, auditing CI triggers to remove unnecessary ones, and Docker layer caching to reduce image pull sizes.&lt;&#x2F;p&gt;
&lt;p&gt;The real question is not self hosting versus managed CI. It is about where you want your engineering team to spend its time. If you enjoy tuning CI performance, have a platform team ready to support it, and want full control, self hosting might be the right call. But if your team would rather focus on building product and moving fast, the hidden costs of running your own CI stack can slow you down. GitHub hosted runner prices dropped 39 percent in January 2026. For most small teams, hosted runners now offer the best value. Self hosting only makes sense for teams with specific compliance, security, or complex autoscaling requirements.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;debugging-without-visibility&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#debugging-without-visibility&quot; aria-label=&quot;Anchor link for: debugging-without-visibility&quot;&gt;Debugging without visibility&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When GitHub Actions jobs fail unexpectedly, memory exhaustion is often the culprit, but the symptoms are not always obvious in the logs. Rather than guessing, you can add simple monitoring steps to your workflows that capture resource usage before and after critical operations.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;heck memory usage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;Memory usage before:&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    free -h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    df -h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    # Your actual build&#x2F;test steps here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;Memory usage after:&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    free -h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; M&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;onitor CPU usage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;CPU info:&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    nproc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    lscpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    echo &amp;quot;Load average:&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    uptime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    time make build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This approach requires no external dependencies or API keys, just a few extra workflow steps that output directly to your job logs. The downside is that you now have to spend time searching through your logs to find where these values were outputted and keep track of them if there are multiple outputs.&lt;&#x2F;p&gt;
&lt;p&gt;Exit code 137 means SIGKILL from the OOM Killer. You can check kernel logs with &lt;code&gt;dmesg | grep -i &quot;oom\|killed process&quot;&lt;&#x2F;code&gt; if you have the right permissions on self hosted runners. You can also check cgroup memory events with &lt;code&gt;cat &#x2F;sys&#x2F;fs&#x2F;cgroup&#x2F;$(cat &#x2F;proc&#x2F;self&#x2F;cgroup | cut -d: -f3)&#x2F;memory.events&lt;&#x2F;code&gt; and look for the oom_kill counter being greater than zero. For containerized jobs, &lt;code&gt;docker inspect &amp;lt;container_id&amp;gt; --format=&#x27;{{.State.OOMKilled}}&#x27;&lt;&#x2F;code&gt; tells you directly.&lt;&#x2F;p&gt;
&lt;p&gt;The common root causes for memory issues include the host OOM Killer which shows up in dmesg, Docker memory limits which show up in docker inspect, cgroup v2 inheritance where the memory max is set too low, and concurrent jobs sharing one runner. The fixes are to increase runner RAM, reduce concurrency, raise or remove Docker memory flags, configure systemd slices for Docker, or set max parallel in your workflow matrix.&lt;&#x2F;p&gt;
&lt;p&gt;For CPU bottlenecks, the symptoms are jobs taking longer than expected without obvious errors, uptime showing load averages greater than the number of cores, and time showing high user or system time relative to wall time. You can add a diagnostic step that runs &lt;code&gt;ps aux --sort=-%cpu | head -10&lt;&#x2F;code&gt; to see the top CPU consumers.&lt;&#x2F;p&gt;
&lt;p&gt;Memory leaks in test suites are a common source of CI failures. For Python, you can use pytest-memray and add markers like &lt;code&gt;@pytest.mark.limit_memory(&quot;24 MB&quot;)&lt;&#x2F;code&gt; to enforce limits. For JavaScript, you can run Jest with &lt;code&gt;--detectLeaks&lt;&#x2F;code&gt; and &lt;code&gt;--runInBand&lt;&#x2F;code&gt; flags along with &lt;code&gt;--max-old-space-size=512&lt;&#x2F;code&gt; to catch leaks. Common leak sources include event listeners not removed in afterEach or afterAll, timers and intervals not cleared, database and network connections not closed, mocks and spies not restored, and global state not reset between tests.&lt;&#x2F;p&gt;
&lt;p&gt;According to Datadog’s 2024 DevOps Report, 63 percent of pipeline failures stem from resource exhaustion. The key metrics to monitor are CPU and memory usage per runner with alerts if greater than 80 percent for 5 or more minutes, network latency between services with less than 50ms being ideal, and disk I&#x2F;O throughput on build servers. Without infrastructure monitoring, CI failures become harder to diagnose and fix, making them more likely to cause extensive downtime.&lt;&#x2F;p&gt;
&lt;p&gt;The hidden cost of flaky tests and re runs adds up quickly. Re running a 30 minute job 3 times means 90 minutes of billable time. Developer trust erodes as teams start ignoring CI failures and missing real bugs. Flaky CI blocking urgent hotfixes during incidents is a nightmare scenario. And the context switching of engineers debugging phantom failures instead of shipping is a productivity killer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automating-the-maintenance-burden&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#automating-the-maintenance-burden&quot; aria-label=&quot;Anchor link for: automating-the-maintenance-burden&quot;&gt;Automating the maintenance burden&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One of the most tedious aspects of maintaining CI infrastructure is keeping forks and patches up to date. If you run custom GitHub Actions runners, you probably maintain a fork of the upstream runner images with modifications for your specific needs. Keeping that fork in sync with upstream requires significant developer effort that compounds over time. Each pull from upstream involves pulling in dozens of commits, reviewing every change for compatibility issues, and ensuring that everything introduced by upstream will be compatible with your existing runner software.&lt;&#x2F;p&gt;
&lt;p&gt;It is not just the raw time investment that is a problem. It is the cognitive load of context switching from other deep and intensive work to this task. Context switching is one of the biggest hidden killers of developer productivity. It shatters whatever flow you had going.&lt;&#x2F;p&gt;
&lt;p&gt;Some teams have started using AI agents to automate this process. The idea is to have a CI workflow that runs daily, checks if upstream has changed, and uses an AI agent to regenerate patches and analyze breaking changes. The agent attempts to apply existing patch files, and if they fail, it modifies the patches to apply cleanly while preserving all the necessary modifications. The agent reads the patch file, examines the upstream changes, and modifies the patch to apply cleanly. A script then tests the updated patch to verify it works.&lt;&#x2F;p&gt;
&lt;p&gt;For analyzing breaking changes, you can create a base session that contains all the historical context about what kinds of upstream changes have caused issues in the past. Things like Docker Compose version mismatches between architectures, PowerShell execution permission changes, kernel upgrades, and BuildKit version bumps. The agent can then analyze new upstream changes against this historical context and flag potential breaking changes before they break anything.&lt;&#x2F;p&gt;
&lt;p&gt;The workflow creates draft pull requests that engineers review before merging. You can view the full agent session to understand exactly what decisions it made and why it chose a particular approach. If the automated fix does not work correctly, the PR stays in draft state and you handle the conflicts manually. This safety net means you can reduce manual intervention from weekly to occasional while maintaining quality control over critical infrastructure changes.&lt;&#x2F;p&gt;
&lt;p&gt;What used to consume hours of developer time every week now runs automatically in the background. Patches stay fresh, breaking changes get flagged before they break anything, and you can focus on building features instead of maintaining forks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-platform-engineering-perspective&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-platform-engineering-perspective&quot; aria-label=&quot;Anchor link for: the-platform-engineering-perspective&quot;&gt;The platform engineering perspective&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;71 percent of platform engineering teams say streamlining CI&#x2F;CD pipelines is their top priority. That number climbs to 85 percent for mid sized organizations. It tracks. The more mature the platform effort, the more painful slow builds become. Meanwhile, platform engineering itself is gaining traction. 67 percent of organizations have either adopted it or are actively exploring it. As more teams shift away from scattered DevOps tooling, a clear pattern is emerging. CI&#x2F;CD performance is where platform work starts.&lt;&#x2F;p&gt;
&lt;p&gt;The average Docker build takes 5 to 15 minutes. Multiply that by several deploys a day and developers can easily lose 30 to 45 minutes waiting every single day. Across a team, that adds up fast. The impact is not just time lost. GitHub Actions bills scale with team size. Productivity drops. Build wait times are the top complaint in developer experience surveys. Platform engineering teams recognize this as an infrastructure problem, not a process problem.&lt;&#x2F;p&gt;
&lt;p&gt;The mindset shift is treating builds as infrastructure rather than just part of development. Just as you would not accept slow database queries, slow builds represent an infrastructure bottleneck. Instead of asking each dev team to optimize their own builds, platform teams provide centralized build acceleration as a service. They track build performance as a core developer experience metric, not an afterthought.&lt;&#x2F;p&gt;
&lt;p&gt;Smart platform teams treat build infrastructure with the same rigor as production infrastructure. Standardized build environments across all projects. Performance monitoring and alerting for build pipelines. Cost tracking and optimization at the infrastructure level.&lt;&#x2F;p&gt;
&lt;p&gt;When explaining CI costs to finance leadership, frame the spend around three core pillars. First, why you bought the tool in the first place. Tie the decision back to speed, quality, and outcome goals. Maybe your CI tool enabled your team to jump from weekly to daily deploys. That is the ROI everyone can get behind. Second, what metrics you are responsible for. Lead time to production, build success rate, mean time to recovery, and infrastructure cost per build are all strong options. Third, where you are succeeding and where you are not. Be honest. If builds are slow or flaky, say so and show how those hiccups have impacted business KPIs.&lt;&#x2F;p&gt;
&lt;p&gt;The 2025 State of Software Delivery benchmarks show that the median build duration is 2 minutes 43 seconds with a target of 10 minutes, median mean time to recovery is 63 minutes 50 seconds with a target of 60 minutes, and median success rate is 90 percent. Use these benchmarks to show what best in class CI&#x2F;CD looks like in your industry. Not to copy them, but to demonstrate you understand what good looks like and where you stand.&lt;&#x2F;p&gt;
&lt;p&gt;GitHub Actions usage reporting does not tell the full story. If you are running different types of runners like 4 core or 8 core or larger, those minutes are not equal and your total usage number does not reflect it. To get accurate numbers, export your usage report from GitHub billing, then normalize your minutes using multipliers. A 4 core runner has a multiplier of 2, an 8 core runner has a multiplier of 4, a 16 core runner has a multiplier of 8, and a 32 core runner has a multiplier of 16. For each runner type, multiply the quantity by the multiplier and sum these normalized values across all runner types. This gives you the total compute equivalent minutes your team used during the period. Without normalized data, you are likely underestimating usage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-dream&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-dream&quot; aria-label=&quot;Anchor link for: the-dream&quot;&gt;The dream&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Despite all the pain, GitHub Actions is still the most practical CI system for many projects. It is integrated with GitHub, it scales automatically, and the ecosystem of actions is huge. But it is not the only option anymore. Buildkite offers better reliability, easier self hosting, and features like test analytics and automatic retries that GitHub Actions lacks. For teams that have outgrown GitHub Actions, the migration is worth considering.&lt;&#x2F;p&gt;
&lt;p&gt;To be fair, the 75 engineer threshold is anecdotal. No rigorous study backs this number. Some 200 person teams run fine on Actions while some 30 person teams hit walls due to monorepo size or build complexity. And the migration cost is real. Rewriting all workflows from GitHub Actions YAML to Buildkite’s format is nontrivial. The ecosystem of Marketplace actions does not transfer. GitHub is also actively improving. Their stated priority is now availability first, capacity second, features third. Whether they execute remains to be seen.&lt;&#x2F;p&gt;
&lt;p&gt;The dream is a CI pipeline that runs in seconds, catches all the bugs, and never gives false positives. We are not there yet. But understanding how the pieces fit together, from Docker layers to BuildKit caching to runner architecture to security gotchas, at least gives you a fighting chance. The green checkmark should feel like validation, not a hostage release. With enough optimization and enough understanding of the system, it can.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>All sorts of famous Attention Layers</title>
          <pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/all-sorts-of-famous-attention-layers/</link>
          <guid>https://harsh-ps-2003.github.io/writes/all-sorts-of-famous-attention-layers/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/all-sorts-of-famous-attention-layers/">&lt;p&gt;Well, we had a bomb of Kimi K3 launch, and I writing this after going through it. So, we will trace this pokemon evolution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#basics&quot; aria-label=&quot;Anchor link for: basics&quot;&gt;Basics&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before Transformers, models like RNNs and LSTMs processed text sequentially, word by word. This process was slow and models struggled to remember information from the distant past, creating a long-range dependency problem. The attention mechanism solved this by allowing the model to look at all parts of the input sequence simultaneously and assign importance (attention) scores to each word, creating a rich context vector. It abandoned sequential processing entirely, enabling parallel computation and providing the model with a direct, weighted memory of its entire input.&lt;&#x2F;p&gt;
&lt;p&gt;I mean, if you’re reading my blogs, most probably you know what the attention is, but for reiteration, the standard softmax based attention equation looks like :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Attention(k, Q, V) = softmax(QK^T^ &#x2F; d^1&#x2F;2^)V&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The attention process :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        B&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; batch size, sequence length, embedding dimensionality (n_embd)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; calculate query, key, values for all heads in batch and move head forward to be the batch dim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_attn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_embd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;B&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (B, nh, T, hs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;B&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (B, nh, T, hs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;B&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (B, nh, T, hs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; manual implementation of attention&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        att&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        att&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; att&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;masked_fill&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bias&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; float&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-inf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        att&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;softmax&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;att&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        att&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;attn_dropout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;att&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; att&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (B, nh, T, T) x (B, nh, T, hs) -&amp;gt; (B, nh, T, hs)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contiguous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;B&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; re-assemble all head outputs side by side&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; output projection&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;resid_dropout&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;c_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the final hidden-state matrix is produced, the language model head maps it into vocabulary logits. During autoregressive decoding, only the logits at the final position are needed to select the next token.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;there-is-a-variety&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#there-is-a-variety&quot; aria-label=&quot;Anchor link for: there-is-a-variety&quot;&gt;There is a variety!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Linear Attention is not a variant of Self-Attention. I used to think that so clarifying here, some papers blur the line. MLA (DeepSeek) is still softmax-based but uses low-rank projections. The hybrid models like Kimi K3 or Qwen3 mix both.&lt;&#x2F;p&gt;
&lt;p&gt;it’s a fundamentally different formulation that replaces the softmax based attention mechanism entirely.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Attention = softmax(QK^T &#x2F; √d) V # O(n²) - must compute full n×n matrix
Attention = φ(Q)(φ(K)^T V) # O(n) - associativity trick&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;By removing softmax and using a kernel function φ, you can change the order of operations. instead of (QK^T^)V which requires the n×n matrix, you compute K^T^ V first (d×d matrix), then multiply by Q. This is the kernel trick that makes it linear.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Attention Mechanisms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Softmax-based Attention (Quadratic O(n²))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Self-Attention (vanilla)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Multi-Head Attention (MHA)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Multi-Query Attention (MQA)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Grouped-Query Attention (GQA)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Sliding Window Attention (sparse, but still softmax)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── Multi-Head Latent Attention (MLA) - low-rank, but still softmax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Faster Softmax Attention (same maths, better memory access via implementation optimizations)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Flash Attention - tiled SRAM computation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Flash Attention 2 - better parallelism&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Flash Attention 3 - Hopper optimizations&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── Paged Attention - dynamic KV cache allocation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;├── Linear Attention (O(n), and no softmax)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Linear Attention (Katharopoulos 2020) - kernel trick&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── DeltaNet - delta rule updates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── Gated DeltaNet - with gating&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   ├── RetNet - retention mechanism&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│   └── RWKV - time-mixing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└── State-Space Models (not attention at all)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ├── S4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ├── Mamba&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    └── Mamba-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;attention-patterns.png&quot; alt=&quot;Attention patterns comparison&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The visualization makes the differences clear. Dense attention fills the entire matrix (O(n²)). Linear attention only tracks a diagonal state that grows with sequence position. Sparse attention skips positions. Flash Attention computes the same dense pattern but tiles it for better memory access. Paged Attention handles variable-length sequences with dynamic allocation. Local&#x2F;Sliding Window attention restricts each token to only attend to nearby tokens.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-look&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-to-look&quot; aria-label=&quot;Anchor link for: where-to-look&quot;&gt;where to look?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Memory is the bottleneck in inference :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For every single token generated, the model must stream billions of parameters (weights) through the memory bus. The GPU spends more time moving data in and out of memory than doing actual mathematical calculations.&lt;&#x2F;li&gt;
&lt;li&gt;The KV cache stores the context and history of a prompt. Longer prompts and agentic workflows require exponentially more space, which reduces concurrent request capacity and limits batch sizes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;when-does-it-even-matter&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-does-it-even-matter&quot; aria-label=&quot;Anchor link for: when-does-it-even-matter&quot;&gt;when does it even matter?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;the attention mechanism matters less than you think (at moderate context).
At 4k tokens with hidden_size=2048, the compute breakdown per transformer layer is roughly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Feed-Forward Network (FFN): ~130 GFLOPs (two matmuls: up-proj and down-proj through a 4x expansion)&lt;&#x2F;li&gt;
&lt;li&gt;Attention (including QKV projections): ~70 GFLOPs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The quadratic Q@K^T attention itself is only ~2 GFLOPs (4000² × 64 per head × num_heads). That’s a tiny fraction. The rest of attention’s cost is the linear projections (Q, K, V, O), which are the same regardless of whether you use full attention, linear attention, Mamba, or anything else.&lt;&#x2F;p&gt;
&lt;p&gt;so, at sequence lengths below ~8k tokens, the attention pattern barely matters. The FFN dominates. Linear attention, sliding window, sparse patterns, they all optimize the O(n²) part which isn’t the bottleneck. The O(n × d × 4d) FFN is. This changes above ~16k tokens where the quadratic attention term starts dominating&lt;&#x2F;p&gt;
&lt;h2 id=&quot;softmax-magic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#softmax-magic&quot; aria-label=&quot;Anchor link for: softmax-magic&quot;&gt;Softmax Magic&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Softmax is a normalizing function that depends on all elements in its input:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;softmax(x_i) = exp(x_i) &#x2F; Σ_j exp(x_j)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To compute the output for any single element, you need the sum over all elements. This is the coupling.&lt;&#x2F;p&gt;
&lt;p&gt;Applying to attention :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;attention_weights_t = softmax([q_t·k_1, q_t·k_2, …, q_t·k_n])&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To normalize q_t’s attention over key k_5, you need to know q_t’s dot product with k_1, k_2, k_3, k_4, k_6, …, k_n. You can’t compute the attention weight for one key without knowing the scores for all keys.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# What we want (efficient):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output = Q @ (K.T @ V)  # compute K.T @ V first: (d×n) @ (n×d) = d×d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         # then Q @ result: (n×d) @ (d×d) = n×d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         # Total: O(n·d²)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# What softmax forces:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;scores = Q @ K.T         # n×n matrix - unavoidable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;weights = softmax(scores, dim=-1)  # needs full row to normalize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output = weights @ V     # n×d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         # Total: O(n²·d)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The softmax sits between the two matrix multiplications. You can’t skip computing the n×n scores matrix because softmax needs all n scores in each row to produce each normalized weight.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Standard softmax attention (for comparison)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; forward&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; past_kv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    d_head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    qkv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;qkv_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; KV cache: concat past keys&#x2F;values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; past_kv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;past_kv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;past_kv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; O(t²) attention computation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    scores&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; math&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; past_kv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; prefill needs causal mask&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        causal_mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;triu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ones&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dtype&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; diagonal&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        scores&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; scores&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;masked_fill&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;causal_mask&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; float&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-inf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    attn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; scores&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;softmax&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; this breaks associativity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; attn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contiguous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Softmax Attention has perfect recoverability. Query k₅, get v₅.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;self-attension&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#self-attension&quot; aria-label=&quot;Anchor link for: self-attension&quot;&gt;Self-Attension&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It’s at the core of transformer models.  Clearly, as HBM (around 1.5 TB&#x2F;s) is not the fastest thing off GPU (its not on GPU, its a chip nearby), the K,V being stored in it are problematic. So, its quadratic complexity for HBM accesses with respect to sequence length at inference is clearly bad at scale.  Lots of techniques to reduce the amount of KV data transferred between the GPU and the HBM.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Algorithm 0 - Standard Attention Implementation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Require: Matrices Q, K, V e RNxd in HBM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1: Load Q, K by blocks from HBM, compute S = QKT, write S to HBM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2: Read S from HBM, compute P = softmax(S), write P to HBM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3: Load P and V by blocks from HBM, compute O = PV, write O to HBM.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4: Return O.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;transformers&#x2F;blob&#x2F;f208766a6551d381475cd8eeed1256f9a5af7b65&#x2F;src&#x2F;transformers&#x2F;models&#x2F;bert&#x2F;modeling_bert.py#L143&quot;&gt;refer Multi-Head Attention in BERT for reference&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;mqa-gqa-mha-mla.png&quot; alt=&quot;MQA vs GQA vs MHA vs MLA comparison&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The diagram shows the progression. In MHA every head has its own K and V. In GQA groups of heads share K and V. In MQA all heads share a single K and V. In MLA the K and V are compressed through a latent projection before being used.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multi-query-attention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-query-attention&quot; aria-label=&quot;Anchor link for: multi-query-attention&quot;&gt;Multi-Query Attention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It’s almost like Self-Attension. Just that Vi and Ki (i being used by each head) is not required. We can use same set of K and V across heads. So, just one K and one V tensor shared across all heads. Thus, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1911.02150&quot;&gt;one head is all you need!&lt;&#x2F;a&gt; So, a great optimization wrt to amount of data that would be required to be loaded via HBM. As the KV is cached as well, we need much less cache. Awesome! Less memory pressure (so you can batch more) and faster decoding on inference. But, there is a small accuracy drop as we have few params. Also, you have to train the model with MQA, can’t just a MHA trained model and use MQA on inference. And, no Tensor parallelism as then we will kinda defeat the purpose by having KV replicated across clusters.&lt;&#x2F;p&gt;
&lt;p&gt;The tradeoff is clear. MQA gives you efficiency by sharing keys and values but you lose some of the nuanced token level interactions that separate heads would capture. Each head still has its own queries so it can focus on different aspects of the input but the shared keys and values mean less diversity in what gets attended to.&lt;&#x2F;p&gt;
&lt;p&gt;You can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;transformers&#x2F;blob&#x2F;f208766a6551d381475cd8eeed1256f9a5af7b65&#x2F;src&#x2F;transformers&#x2F;models&#x2F;falcon&#x2F;modeling_falcon.py#L274&quot;&gt;refer Falcon 7B for reference for MQA&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;group-query-attension&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#group-query-attension&quot; aria-label=&quot;Anchor link for: group-query-attension&quot;&gt;Group Query Attension&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Well, it’s between MHA and MQA. Just adding another hyparam to the equation, pairing up (K, V) to some heads. This gives best of both world, a nice compromise balance between speed and accuracy.  4 and 8 were quite good. Interesting thing here is that MHA models can be uptrained (not really fine-tuning, just an upgrade) to GQA.  And clearly a better fit to tensor parallelism.&lt;&#x2F;p&gt;
&lt;p&gt;The way it works is that input queries get divided into groups. For each group a shared set of key and value representations is computed. Attention scores are calculated between the grouped queries and the shared key representations. The final output is a weighted sum of the shared value representations based on those attention scores. Then outputs of all query groups get combined to produce the final representation.&lt;&#x2F;p&gt;
&lt;p&gt;GQA scales more effectively with sequence length than MHA. Llama and Mistral both use it. The grouping preserves more diversity than MQA while still being more efficient than full MHA.&lt;&#x2F;p&gt;
&lt;p&gt;This can be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;transformers&#x2F;blob&#x2F;f208766a6551d381475cd8eeed1256f9a5af7b65&#x2F;src&#x2F;transformers&#x2F;models&#x2F;llama&#x2F;modeling_llama.py#L209&quot;&gt;referenced from Llama 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sliding-window-attention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sliding-window-attention&quot; aria-label=&quot;Anchor link for: sliding-window-attention&quot;&gt;Sliding Window Attention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In vanilla attention, we compute attention score from all token, and at inference time we mask becuase we dont want decoding to look at the future. We have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@sayedebad.777&#x2F;mastering-mistral-ai-from-sliding-window-attention-to-efficient-inference-22d944384788&quot;&gt;triangle shaped attention mask&lt;&#x2F;a&gt; which is quadratic. What SWA does is that it limits the self attention computation to a fixed window so we get a fixed cached size. So, we can’t see more than window size from previous token. KV cache becomes a rotating buffer. So, the max context size would be window size * number of layers, reducing attention complexity to linear. So, we are shortening the attention span.&lt;&#x2F;p&gt;
&lt;p&gt;Sliding window is just one type of sparse attention pattern. There are others worth knowing about. Strided attention has each token attend to every kth token which is useful for capturing periodic patterns. Reformer uses locality sensitive hashing to cluster similar queries and keys into buckets so queries only attend to keys in the same bucket giving O(n log n) complexity. BigBird combines random attention with local attention with global attention. Longformer uses local sliding window attention with task specific global attention where some tokens like CLS attend to all tokens while others use local attention.&lt;&#x2F;p&gt;
&lt;p&gt;The tradeoff with sparse patterns is loss of global context. Fixed patterns may miss long range dependencies. Choosing the right sparsity pattern is task dependent. But for long sequences the memory savings are worth it. Reformer can handle 64K tokens. Longformer works well for summarizing legal contracts or books.&lt;&#x2F;p&gt;
&lt;p&gt;You can refer &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2310.06825&quot;&gt;Mistral 7B paper&lt;&#x2F;a&gt; and reference &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;transformers&#x2F;blob&#x2F;f208766a6551d381475cd8eeed1256f9a5af7b65&#x2F;src&#x2F;transformers&#x2F;masking_utils.py#L1118&quot;&gt;sliding window causal mask code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;flash-attenstion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#flash-attenstion&quot; aria-label=&quot;Anchor link for: flash-attenstion&quot;&gt;Flash Attenstion&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;As we know, HBM memory is slower to on-GPU memory. Wouldn’t it be better to run the Self-Attension computation on GPU itself (with minimal HBM accesses)? Thats exactly what flash attention does.&lt;&#x2F;p&gt;
&lt;p&gt;The key insight is understanding the GPU memory hierarchy. Small SRAM has extremely high bandwidth around 19 TB&#x2F;s but limited size around 20MB. HBM has higher capacity around 40GB but lower bandwidth around 1.5 TB&#x2F;s. CPU DRAM has massive capacity over 1TB but much slower bandwidth around 12.8 GB&#x2F;s. Flash Attention exploits this hierarchy by keeping intermediate results in fast SRAM instead of writing them to slow HBM.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Load Q and K from HBM once&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Multiply Q and K, keep S in SRAM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Compute P incrementally in SRAM (tiling)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Materializes S = QKᵀ and P = softmax(S) and writes only the final output O&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And, parallize over batch size and number of heads.
Taking N as sequence length, d as embedding length and M as size of SRAM (d&amp;lt;=M&amp;lt;=Nd),
Flash Attention requires O(N^2^d^2^M^-1^) HBM accesses which still looks quadratic. But if M=N, then its O(Nd^2) HBM accesses, so linear wrt sequence length. This optimizes for forward and backward passes, so accelerate training.&lt;&#x2F;p&gt;
&lt;p&gt;The tiling strategy is clever. It divides Q, K, V into blocks sized to fit GPU SRAM. The outer loop loads blocks of K and V from slow HBM into fast SRAM. The inner loop processes Q blocks against the loaded K and V blocks. This enables processing sequences up to 4x longer than conventional attention because you never materialize the full N by N attention matrix.&lt;&#x2F;p&gt;
&lt;p&gt;The fused kernel execution replaces the traditional multi step attention with a unified operation. It combines matrix multiply then scaling then masking then softmax then dropout then matrix multiply into one CUDA kernel. Intermediate results like QK transpose and softmax outputs stay in SRAM and registers. Only final attention outputs get written to HBM. This reduces HBM accesses by 10 to 20x compared to standard PyTorch implementations.&lt;&#x2F;p&gt;
&lt;p&gt;Later, there was FlashAttension-2 that did some rewriting to reduce number of non-matmul operations to maximize GPU throughput. Also, it optimize operations for Multi-Query Attention and Grouped-Query Attention. Even more sequence parallelism. Its over staggering 9x faster than standard attention.&lt;&#x2F;p&gt;
&lt;p&gt;Refer the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2205.14135&quot;&gt;FlashAttension Paper-1&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2307.08691&quot;&gt;paper 2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;paged-attention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#paged-attention&quot; aria-label=&quot;Anchor link for: paged-attention&quot;&gt;Paged Attention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5ZlavKF_98U&quot;&gt;famous vLLM optimization which enables the KV cache memory grows and shrinks dynamically for each inference request&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with standard KV caching is that each request gets its own dedicated KV cache block. Tokens are appended sequentially forming a contiguous memory block. There is no sharing between sequences even if parts of their content are the same. This leads to memory waste due to fixed and unshared allocation and poor handling of varying prompt lengths across sequences.&lt;&#x2F;p&gt;
&lt;p&gt;Paged Attention draws inspiration from virtual memory paging in operating systems. It introduces a separation between logical KV cache blocks which is the abstract token layout that each sequence sees and physical KV cache blocks which is the actual memory pages storing keys and values that may be shared across sequences. Each token’s data is stored in small fixed size memory pages. Pages are dynamically allocated and mapped via a page table. Multiple logical sequences can share the same physical memory if their tokens match like a common prefix. This enables non contiguous memory access through logical to physical translation.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it like OS virtual memory where different processes see the same memory contents using their own mappings.&lt;&#x2F;p&gt;
&lt;p&gt;During generation the attention mechanism gathers keys and values for a sequence by following its page table. Sequences with shared prefixes map to the same physical cache blocks. When a sequence diverges Paged Attention uses copy on write. The shared page is cloned. Only the diverging sequence gets the new page. Reference count for shared pages is decremented. This ensures efficient memory use while allowing flexibility in generation.&lt;&#x2F;p&gt;
&lt;p&gt;THe KV cache without pagedAttention is a rectangle with batch vs max seq length. a lot of space wasted in the rectangle, because users dont really use the seq length to its max. we wanted to improve upon this device memory issue. pagedAttention allocates blocks in GPU memory. so you first load your model and see how much space you have left, and then everything else is filled with memory blocks. when new sequence comes in, we allocate as many blocks it needs for the prompt, and slowly grow them as needed.  The management of cache was kinda an old school OS problem in the hindsight. GPU memory fragmentation wastes memory and makes it difficult to increase batch size. So, Paged Attention simply divides the KV cache into fixed-size memory-aligned blocks (pages dont have memory between them), similar to virtual memory pages in operating systems and allocating pages reduces internal and external memory fragmentation.&lt;&#x2F;p&gt;
&lt;p&gt;Refer the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2309.06180&quot;&gt;paper&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multi-head-latent-attention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#multi-head-latent-attention&quot; aria-label=&quot;Anchor link for: multi-head-latent-attention&quot;&gt;Multi-Head Latent Attention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Got introduced in Deepseek v2 (also used in v3). This literally avoids caching K, V altogether. A low-rank representation of K and V learned during training is cached instead (LoRA like). This gives us much less KV cache use (90%+ savings). Also, as metrix size is also reduced, a good 5-6x inference speedup is there. And interestingly higher accuracy than MHA is achieved.&lt;&#x2F;p&gt;
&lt;p&gt;The key innovation is introducing learnable latent embeddings that act as intermediaries between queries keys and values. These latent embeddings capture high level abstract patterns and enable more efficient cross token interactions. Instead of attending to all input tokens the attention focuses on these latent embeddings leading to faster computation.&lt;&#x2F;p&gt;
&lt;p&gt;The mechanics work like this. A fixed number of latent embeddings are initialized as part of the model. Input queries attend to these latent embeddings instead of the entire sequence which drastically reduces the number of pairwise interactions. The latent embeddings then attend to the original keys and values acting as intermediaries that distill context into meaningful patterns. Finally the results get projected back to the token space preserving critical token level information.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to MHA which suffers from quadratic complexity MLA achieves linear or near linear complexity by compressing the attention space. Compared to MQA which uses a single shared key value pair MLA maintains diversity by having latent embeddings act as a middle layer allowing richer context capture. Compared to GQA which focuses on groups and can miss global dependencies MLA’s latent embeddings inherently capture global patterns acting as global summaries.&lt;&#x2F;p&gt;
&lt;p&gt;The tradeoff is that compressing input tokens into latent embeddings may lose fine grained details critical for some tasks. The performance also depends on how effectively the latent embeddings are initialized and trained.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linear-magic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#linear-magic&quot; aria-label=&quot;Anchor link for: linear-magic&quot;&gt;Linear Magic&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Linear attention removes the dependency that troubles Softmax.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Feature map applied BEFORE the dot product&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;q_mapped = φ(Q)  # element-wise, no coupling&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;k_mapped = φ(K)  # element-wise, no coupling&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Now we can re-associate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;output = q_mapped @ (k_mapped.T @ V)  # O(n·d²)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;φ (like ELU+1) is applied element-wise - each element transforms independently. No normalization across the sequence. So you can legally reorder the multiplications&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Softmax attention:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;q_1 ──┬── score with k_1 ──┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ├── score with k_2 ──┼── softmax needs ALL ── weight_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ├── score with k_3 ──┤                        weight_2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      └── score with k_n ──┘                        weight_n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Linear attention:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;q_1 ── φ(q_1) ──┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                ├── can compute independently&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;k_1 ── φ(k_1) ──┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With softmax, the denominator Σ exp(q·k_j) couples everything. Without it, each (q, k, v) triplet can be processed independently and accumulated into a running state.&lt;&#x2F;p&gt;
&lt;p&gt;The coupling in softmax gave it expressiveness. the competition between keys (via normalization) lets the model express “attend to this, not that” patterns sharply. Linear attention loses this competitive dynamic, which is why it’s less expressive but more efficient.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;linear-attention&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#linear-attention&quot; aria-label=&quot;Anchor link for: linear-attention&quot;&gt;Linear Attention&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;As softmax applied nonlinearity after Q·K product, coupling every query to every key, we have O(n^2^), that is full N×N attention matrix before applying softmax, as I explained earlier. Linear attention trades expressiveness for efficiency. Softmax attention can express arbitrary attention patterns, any token can attend strongly to any other token. Linear attention’s feature map constrains what patterns are representable. This is why modern hybrids (Kimi K3, Qwen3) use both! softmax layers for complex reasoning, linear layers for efficient long-range propagation.&lt;&#x2F;p&gt;
&lt;p&gt;Linear attention applies a feature map φ (such as ELU+1, or simply ReLU) to Q and K separately, before the dot product:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Softmax:  Attention = softmax(QK^T &#x2F; √d) V     # must compute N×N first&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Linear:   Attention = φ(Q)(φ(K)^T V)           # associativity trick&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I had an obvious question, why ELU+1 is used as the feature map and how linear attention still preserves the attention contract despite removing softmax? Both softmax and linear attention preserve the same fundamental contract, they just implement it differently:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Make QK scores non-negative - Attention weights can’t be negative (obviously). Softmax uses exp(x) which is always positive. Linear attention uses ELU+1, since ELU(x) ≥ -1 for all x, adding 1 guarantees non-negativity.&lt;&#x2F;li&gt;
&lt;li&gt;Normalize by dividing by sum - We still divide by Σ φ(q)·φ(k_j) to get proper weights. This is often omitted from diagrams but it’s there.&lt;&#x2F;li&gt;
&lt;li&gt;Compute weighted average of values - Same as softmax&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Also, ELU(x) is smooth unlike ReLU which helps gradients. It approximates the exponential kernel that softmax uses. Softmax’s exp() function creates a sharper distribution, small differences in scores become large differences in weights. ELU+1 is flatter, so the attention distribution is more diffuse. The model can’t say “attend ONLY to this token” as sharply. This is interesting kernel trick.&lt;&#x2F;p&gt;
&lt;p&gt;Its the game of association. (AB)C = A(BC) from your Linear Algebra class. With softmax, you’re forced into (QK^T^)V because softmax breaks associativity. Without softmax, you can compute (K^T^ V) first, that’s a (d×N) × (N×d) = d×d matrix, independent of sequence length. Then multiply by Q. This means the growing history of K and V vectors can be folded into a fixed D×D state matrix S:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Recurrent form of linear attention&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; d×d state matrix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;seq_len&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; φ&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;k_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;outer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; update state: O(d²)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; φ&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;q_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;               #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; query state: O(d²)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You get it right? Constant memory, constant compute per token. No KV cache that grows with context.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Linear attention equivalent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; forward_linear&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    d_head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    qkv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;qkv_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Apply feature map (ELU+1 is common)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;elu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;elu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;zeros&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;device&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; For each position, update state and compute output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    outputs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; S += k_t ⊗ v_t  (outer product update)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;einsum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bhd,bhe-&amp;gt;bhde&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; o_t = q_t @ S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        o_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;einsum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;bhd,bhde-&amp;gt;bhe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        outputs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;o_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stack&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;outputs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; b, h, t, d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contiguous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; state is fixed d×d, not growing KV cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Notice the difference! softmax attention returns (k, v) that grow with sequence length. Linear attention returns a fixed-size state matrix.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If you see &lt;a href=&quot;tab:https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2006.16236&quot;&gt;original paper&lt;&#x2F;a&gt;, they say &lt;code&gt;the cost per time-step for transformers scales with the square of the current sequence length&lt;&#x2F;code&gt; which might trip you up! Today we know Flash Attention makes softmax attention practical. Well the paper was released in 2020 (a different world altogether).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2020-era: recompute everything, no KV cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; generate_token&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;model&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; all_previous_tokens&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Re-run full forward pass on ALL tokens&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; model&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;qkv_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_previous_tokens&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; O(t × d)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Materialize full t×t attention matrix&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    attn_matrix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; O(t² × d) compute, O(t²) memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    attn_matrix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; softmax&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;attn_matrix&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; attn_matrix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; only need last token&amp;#39;s output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Per-token decode cost was O(t²) without cache in 2020 which became O(t) with cache, and full sequence generation was O(N³) which now is O(N²). Rememeber, algorithmic complexity is not implementation complexity.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Linear Attention has no recoverability guarantee. Query k₅, get a mixture influenced by all tokens with similar keys.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;deltanet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deltanet&quot; aria-label=&quot;Anchor link for: deltanet&quot;&gt;DeltaNet&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Look at Linear Attention State update :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;S = S + φ(k_t).outer(v_t) # additive update&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Softmax Attention (KV Cache) :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cache = [k₁, k₂, k₃, ..., kₙ]  # each token gets its own slot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        [v₁, v₂, v₃, ..., vₙ]  # perfect isolation, O(N) memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Linear attention (state matrix):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S = k₁⊗v₁ + k₂⊗v₂ + k₃⊗v₃ + ... + kₙ⊗vₙ  # all compressed into D×D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you query with q_t, softmax can retrieve v₅ in isolation by attending only to k₅. Linear attention retrieves:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o_t = q_t @ S = q_t @ (k₁⊗v₁ + k₂⊗v₂ + ... + kₙ⊗vₙ)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The information from all previous tokens is superimposed. If k₃ and k₇ are similar, their values interfere, you can’t cleanly separate them. This is called retrieval interference or memory interference. The D×D state matrix has finite capacity. With N tokens compressed into D² slots, information must overlap when N &amp;gt; D². Even before that limit, similar keys cause interference.&lt;&#x2F;p&gt;
&lt;p&gt;DeltaNet addresses this by using the delta rule from associative memory literature, instead of pure addition. the insightful thing here is, instead of blindly adding k⊗v to the state, subtract what’s already there for that key first:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Linear attention (naive additive)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S = S + k_t ⊗ v_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# DeltaNet (delta rule)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S = S + k_t ⊗ (v_t - S @ k_t)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#              ↑ this is the &amp;quot;delta&amp;quot; - the error&#x2F;correction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The term (v_t - S @ k_t) is the delta, the difference between what we want to store (v_t) and what we’d currently retrieve for this key (S @ k_t).&lt;&#x2F;p&gt;
&lt;p&gt;Why this helps:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If k_t is similar to a previous key, S @ k_t already contains that value&lt;&#x2F;li&gt;
&lt;li&gt;We only add the correction, not the full value&lt;&#x2F;li&gt;
&lt;li&gt;This reduces interference from similar keys&lt;&#x2F;li&gt;
&lt;li&gt;It’s inspired by Hopfield networks and fast weight programmers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;This has better recoverability. The delta rule acts like an error correcting update, it tries to make S @ k = v hold for each stored (k, v) pair&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As we see in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2102.11174&quot;&gt;Fast Weight Programmers&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“when the sequence length exceeds storage capacity, the model may end up in an overcapacity regime. To properly operate under such a regime, the model should learn to dynamically interact with the memory contents and selectively decide which key-value associations to keep and which ones to delete. The purely additive instruction may be inappropriate for this purpose… endlessly adding new associations to a memory of finite size, as in Eq. 17, inevitably will reach a limit.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The regime that makes linear attention attractive (N &amp;gt;&amp;gt; D) also exposes its main limitation. Once the state exceeds its effective capacity, associations begin to interfere because the update is purely additive, nothing ever leaves the cache.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; forward&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    d_head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;num_heads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    qkv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;qkv_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; qkv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_head&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;normalize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;silu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;q&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;normalize&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;F&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;silu&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;k&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sigmoid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;w_beta&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; per-token write strength&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v_old&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;              #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; read what&amp;#39;s currently stored at this key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; v_old&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;     #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the delta: only what&amp;#39;s actually new&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; write the correction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; read with query&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contiguous&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;view&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The update first asks what information the current key retrieves from the cache (v_old = k @ S). It subtracts that existing information from the value we want to store, multiplies by beta (write strength), and adds the result back. Old information is removed and new information is written in its place.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gated-deltanet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#gated-deltanet&quot; aria-label=&quot;Anchor link for: gated-deltanet&quot;&gt;Gated DeltaNet&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2406.06484&quot;&gt;Gated DeltaNet&lt;&#x2F;a&gt; adds gating to control how much of the old state to retain vs. overwrite:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Gated DeltaNet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sigmoid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;gate_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; forget gate, per-token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt; ⊗ &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The gate β controls:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;β ≈ 1 - retain most of old state (long-term memory)&lt;&#x2F;li&gt;
&lt;li&gt;β ≈ 0 - forget old state (fresh start)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is analogous to LSTM’s forget gate. it lets the model learn when to forget rather than accumulating everything forever. The model can now selectively decide which associations to keep and which to delete, addressing the overcapacity problem Schlag identified.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;retnet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#retnet&quot; aria-label=&quot;Anchor link for: retnet&quot;&gt;RetNet&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;While DeltaNet was figuring out the delta rule, Microsoft was working on a different angle. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2307.08621&quot;&gt;RetNet&lt;&#x2F;a&gt; (Retentive Network) came out in 2023 with a bold claim, they literally called it a successor to Transformer.&lt;&#x2F;p&gt;
&lt;p&gt;The core idea is the retention mechanism, which is basically linear attention with exponential decay. Instead of the ELU+1 feature map, RetNet uses a decay factor γ that makes older tokens contribute less:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; RetNet retention (simplified)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; γ&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; S_&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt; ⊗ &lt;&#x2F;span&gt;&lt;span&gt;v_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The γ (typically 0.9-0.99) acts like a built-in forgetting mechanism. Older associations naturally fade away, which addresses the overcapacity problem without needing the delta rule’s explicit correction.&lt;&#x2F;p&gt;
&lt;p&gt;What made RetNet interesting was the three computation paradigms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Parallel mode: For training, unfold the recurrence into a matrix form (like standard attention but with a decay mask)&lt;&#x2F;li&gt;
&lt;li&gt;Recurrent mode: For inference, O(1) per token like linear attention&lt;&#x2F;li&gt;
&lt;li&gt;Chunkwise mode: Hybrid for long sequences - parallel within chunks, recurrent across chunks&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Sound familiar? This is exactly the chunking trick that DeltaNet later formalized. RetNet got there first, though with a simpler (non-delta) update rule.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, RetNet showed up in Microsoft’s TorchScale library and influenced later work like YOCO (You Only Cache Once). The Gated RetNet variant added gating similar to Gated DeltaNet. But RetNet never quite took off in production the way the authors hoped, the successor to Transformer claim was kinda premature. Still, the multi-paradigm formulation was influential.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rwkv&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rwkv&quot; aria-label=&quot;Anchor link for: rwkv&quot;&gt;RWKV&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2305.13048&quot;&gt;RWKV&lt;&#x2F;a&gt; is the weird one. It’s not quite attention, not quite an RNN, but somehow both. The name comes from its four main parameters, Receptance, Weight, Key, Value.&lt;&#x2F;p&gt;
&lt;p&gt;The project started as a community effort by BlinkDL and grew into something surprisingly capable. RWKV-4 was the first version that really worked, scaling up to 14B parameters - the largest dense RNN ever trained at the time.&lt;&#x2F;p&gt;
&lt;p&gt;The core mechanism is time-mixing with learned decay:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; RWKV time-mixing (simplified)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wkv_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Σ_&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;w&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_i&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; v_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; v_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sigmoid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;r_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; wkv_t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;w&lt;&#x2F;code&gt; is a learned decay (like RetNet’s γ but in log-space), &lt;code&gt;u&lt;&#x2F;code&gt; is a bonus for the current token, and &lt;code&gt;r&lt;&#x2F;code&gt; (receptance) gates the output. It’s inspired by Apple’s AFT (Attention Free Transformer) but with crucial modifications that make it actually trainable.&lt;&#x2F;p&gt;
&lt;p&gt;What’s cool about RWKV:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;100% attention-free: No QK^T computation at all&lt;&#x2F;li&gt;
&lt;li&gt;Parallelizable training: Can be formulated as a convolution&lt;&#x2F;li&gt;
&lt;li&gt;RNN inference: O(1) memory and compute per token&lt;&#x2F;li&gt;
&lt;li&gt;Actually deployed: There’s a whole ecosystem RWKV-Runner for local inference, rwkvserve for production APIs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The architecture kept evolving:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;RWKV-5 “Eagle” and RWKV-6 “Finch”: Added matrix-valued states and dynamic recurrence&lt;&#x2F;li&gt;
&lt;li&gt;RWKV-7 “Goose”: Incorporated a generalized delta rule (yes, the same delta rule from DeltaNet!)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;From the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2503.14456&quot;&gt;RWKV-7 paper&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“RWKV-7 introduces a newly generalized formulation of the delta rule with vector-valued gating and in-context learning rates”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So the field is converging, RWKV started from RNNs and added delta-rule-like updates, while DeltaNet started from linear attention and added gating. They’re meeting in the middle.&lt;&#x2F;p&gt;
&lt;p&gt;RWKV is actually used in production. The community has trained models up to 14B parameters, there are multilingual variants, music generation models, and even edge deployment with quantization. It’s one of the few non-Transformer architectures that has a real user base beyond research papers.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;the-prefill-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-prefill-problem&quot; aria-label=&quot;Anchor link for: the-prefill-problem&quot;&gt;The Prefill Problem&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;All the code I’ve shown so far has a dirty secret - it’s sequential. Look at the linear attention loop:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; can&amp;#39;t parallelize - each step depends on previous S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each step depends on the previous state. GPUs hate this. They want big parallel matrix multiplies, not tiny sequential ones. This is why naive linear attention is slower than Flash Attention in practice despite being O(n) vs O(n²).&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;tab:https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2406.06484&quot;&gt;DeltaNet&lt;&#x2F;a&gt; paper solves this with chunking. Split the sequence into chunks of size C, then within each chunk, do normal quadratic attention (parallel, GPU-friendly) and across chunks, use the recurrent state update (sequential, but only T&#x2F;C steps instead of T)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;zeros&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; h&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; dh&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; dh&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;outs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    q_c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    k_c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; k&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v_c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; contribution from all previous chunks (recurrent)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o_prev&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q_c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; contribution from within this chunk (parallel attention)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    attn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;q_c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k_c&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tril&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; masked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o_curr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; attn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v_c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o_prev&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; o_curr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; update state for next chunk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_c&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transpose&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; v_c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    outs&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;outs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dim&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The cost splits into two parts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed: 2Ld² for state updates (doesn’t depend on C)&lt;&#x2F;li&gt;
&lt;li&gt;Growing: 2LCd for the within-chunk attention matrices&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Setting C=N recovers full O(N²) attention. Setting C=1 gives pure sequential linear attention. In practice, C=64 or C=128 works well because that’s the granularity where tensor cores (UMMA instructions) operate efficiently.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;chunking-deltanet-is-harder&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#chunking-deltanet-is-harder&quot; aria-label=&quot;Anchor link for: chunking-deltanet-is-harder&quot;&gt;Chunking DeltaNet is Harder&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The chunking trick doesn’t directly work for DeltaNet because the delta correction needs the current state:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;v_old = k_i @ S  # need S at this exact moment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;u_i = beta * (v - v_old)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can’t batch this naively. The paper’s solution is a mathematical reparameterization that rewrites the delta update as a matrix recurrence with Householder-like transition matrices. This allows computing all C deltas within a chunk simultaneously using a forward substitution trick.&lt;&#x2F;p&gt;
&lt;p&gt;I won’t pretend I understood this tbh. It took me hours to grasp a little. The key insight is that the sequential dependency can be “unrolled” into a form where you solve a triangular system once per chunk, then everything else parallelizes.&lt;&#x2F;p&gt;
&lt;p&gt;The full chunked DeltaNet forward pass looks something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; chunk_delta_rule_forward&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; K&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; V&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; beta&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    L&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; K&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; V&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;lambda&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reshape&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;Q&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; K&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; V&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; beta&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reshape&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    K_beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; K&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; beta&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;unsqueeze&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    V_beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; V&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; beta&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;unsqueeze&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Forward substitution for the correction terms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;K_beta&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; K&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tril&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        T&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;eye&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    W&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; K_beta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    U&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; V_beta&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Chunked parallel computation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;zeros&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    O&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;empty_like&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;V&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;L&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; C&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        q_i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; k_i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; w_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; Q&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; K&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; W&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; U&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; w_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; corrections for this chunk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        o_inter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; q_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; cross-chunk contribution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        A_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;q_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k_i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tril&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        o_intra&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; A_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; u_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; within-chunk contribution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; k_i&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; u_i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; update state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        O&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o_intra&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; o_inter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; O&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reshape&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;L&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The forward substitution (the T matrix computation) is the magic that makes this work. It precomputes how each position’s delta affects subsequent positions within the chunk.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;kimi-delta-attention-kda&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#kimi-delta-attention-kda&quot; aria-label=&quot;Anchor link for: kimi-delta-attention-kda&quot;&gt;Kimi Delta Attention (KDA)&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;kda-architecture.png&quot; alt=&quot;Kimi Delta Attention architecture&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The core innovation is Kimi Delta Attention (KDA), which extends Gated DeltaNet with fine-grained gating. Instead of a single scalar decay β, KDA learns a separate decay value for each channel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Gated DeltaNet: single scalar gate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sigmoid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;gate_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; shape: (batch, seq, 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt; ⊗ &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;v_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; β&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; @&lt;&#x2F;span&gt;&lt;span&gt; k_t&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; KDA: per-channel gate (fine-grained)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;α&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sigmoid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;alpha_proj&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; shape: (batch, seq, d_head)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; each dimension of the state decays at its own rate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The diagram shows the full KDA block. Q and K go through L2 normalization and convolutions. V goes through a convolution as well. The α and β parameters come from separate linear projections with sigmoid gates. Everything feeds into the Gated Delta Rule which is the core state update. The output goes through RMSNorm and a final linear projection. The 3:1 ratio at the bottom shows how layers are arranged in Kimi Linear and K3. Three KDA layers followed by one Gated Multi-head Latent Attention layer then repeat.&lt;&#x2F;p&gt;
&lt;p&gt;Why does this matter? The D×D state matrix has limited capacity. With a single scalar decay, all channels forget at the same rate. With per-channel decay, the model can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Keep some channels as long-term memory (high α)&lt;&#x2F;li&gt;
&lt;li&gt;Use other channels as short-term scratch space (low α)&lt;&#x2F;li&gt;
&lt;li&gt;Learn which information needs persistence vs. which can be overwritten&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;kimi-linear&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#kimi-linear&quot; aria-label=&quot;Anchor link for: kimi-linear&quot;&gt;Kimi Linear&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This was Moonshot AI’s approach before K3. The idea was simple, if softmax attention is expensive at long contexts and linear attention loses expressiveness, why not use both?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;tab:https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2510.26692&quot;&gt;Kimi Linear&lt;&#x2F;a&gt; made a bold claim :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We introduce Kimi Linear, a hybrid linear attention architecture that, for the first time, outperforms full attention under fair comparisons across various scenarios—including short-context, long-context, and reinforcement learning (RL) scaling regimes.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;They used a hybrid architecture:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Early layers: Linear attention (cheap, handles long-range dependencies)&lt;&#x2F;li&gt;
&lt;li&gt;Later layers: Softmax attention (expensive, but more expressive for final reasoning)
The intuition is that early layers do broad gathering of information across the context, while later layers do precise reasoning that benefits from softmax’s sharp attention patterns.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Kimi Linear doesn’t use KDA alone. It interleaves KDA layers with Multi-Head Latent Attention (MLA) layers in a 3:1 ratio. The obvious question that would come to anyones mind is why MLA? MLA (from DeepSeek) is a softmax-based attention that uses low-rank projections to reduce KV cache size. By mixing KDA (linear, O(1) state) with MLA (softmax, but compressed), Kimi Linear gets:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;75% reduction in KV cache compared to full MLA&lt;&#x2F;li&gt;
&lt;li&gt;Up to 6× decoding throughput at 1M context length&lt;&#x2F;li&gt;
&lt;li&gt;Better quality than pure MLA on benchmarks&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The paper also replaces the standard MLP with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1701.06538&quot;&gt;Mixture-of-Experts (MoE)&lt;&#x2F;a&gt;, but that’s orthogonal to the attention innovation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-moe-landscape&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-moe-landscape&quot; aria-label=&quot;Anchor link for: the-moe-landscape&quot;&gt;The MoE Landscape&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Speaking of MoE, here’s where things get interesting. Kimi K3 isn’t just big, it’s efficiently big.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;moe-landscape.png&quot; alt=&quot;MoE activation comparison&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The activation percentage tells you how much of the model actually runs per token:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Kimi K3: 1.8% activation (104B of 2.8T parameters)&lt;&#x2F;li&gt;
&lt;li&gt;MiniMax M3: 3.1% activation&lt;&#x2F;li&gt;
&lt;li&gt;Inkling (Thinking Machines): 3.1% activation&lt;&#x2F;li&gt;
&lt;li&gt;Nemotron 3 Ultra (NVIDIA): 4.3% activation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;K3 is currently the biggest open MoE model, but what’s more impressive is the small activation ratio. Lower activation means faster inference and lower memory bandwidth requirements. The 1.8% figure means K3 activates roughly half the proportion of parameters that competitors do, while still achieving competitive quality.&lt;&#x2F;p&gt;
&lt;p&gt;The scaling from K2 to K3 tells the story:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;kimi-k2-k3-scaling.png&quot; alt=&quot;Kimi K2 to K3 scaling&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;K2 had 1T parameters with 384 experts, activating 8 per token (2% activation). K3 scaled to 2.8T with 896 experts, activating 16 per token. The math: they nearly tripled the total parameters but only doubled the activated parameters. More experts, sparser activation, better efficiency. This is the MoE scaling playbook - grow the expert pool faster than you grow the activation budget.&lt;&#x2F;p&gt;
&lt;p&gt;This worked reasonably well but had a problem: the transition between linear and softmax layers created a representation mismatch. Information compressed into the D×D state matrix had to be “unpacked” for softmax layers to use effectively.&lt;&#x2F;p&gt;
&lt;p&gt;Previous hybrid approaches (like the early Kimi experiments) stacked linear and softmax layers in separate sections. Kimi Linear interleaves them throughout, which helps maintain representation compatibility. The 3:1 ratio was determined empirically, enough KDA for efficiency, enough MLA for expressiveness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kimi-k3&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#kimi-k3&quot; aria-label=&quot;Anchor link for: kimi-k3&quot;&gt;Kimi K3&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;K3 scales the Kimi Linear architecture to 2.8 trillion parameters with 104 billion activated (it’s an MoE model). To put that in perspective: one K3 contains roughly 22,580 GPT-2 models worth of parameters.
But the interesting part isn’t the scale. It’s what they scaled. K3 uses the same KDA + MLA hybrid from Kimi Linear, but with several additions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;harsh-ps-2003.github.io&#x2F;writes&#x2F;all-sorts-of-famous-attention-layers&#x2F;kimi-k3-architecture.png&quot; alt=&quot;Kimi K3 architecture&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The diagram shows the full picture. On the left, the overall architecture: 93 transformer blocks with the 3:1 KDA&#x2F;MLA ratio (layers 1-3 use KDA, layer 4 uses MLA, repeat). Layer 1 is dense, layers 2-93 use LatentMoE. On the right, the two attention mechanisms side by side - Gated MLA (softmax-based with latent compression) and KDA (the delta rule with per-channel gating via α and β).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;native-multimodality&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#native-multimodality&quot; aria-label=&quot;Anchor link for: native-multimodality&quot;&gt;Native Multimodality&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;K3 is natively multimodal - vision is built into the architecture from the start, not bolted on. The linear attention layers handle the massive context that images require (a single high-res image can be thousands of tokens), while MLA layers do the cross-modal reasoning&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stable-latentmoe&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#stable-latentmoe&quot; aria-label=&quot;Anchor link for: stable-latentmoe&quot;&gt;Stable LatentMoE&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Training a 2.8T parameter model is hard. K3 uses a Stable LatentMoE framework that combines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The MuonClip optimizer (from &lt;a href=&quot;tab:https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2507.20534&quot;&gt;Kimi K2&lt;&#x2F;a&gt;) for training stability&lt;&#x2F;li&gt;
&lt;li&gt;Careful expert routing to prevent collapse&lt;&#x2F;li&gt;
&lt;li&gt;Latent representations that compress the expert outputs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;1m-context-window&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#1m-context-window&quot; aria-label=&quot;Anchor link for: 1m-context-window&quot;&gt;1M+ Context Window&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The combination of KDA’s O(1) state and MLA’s compressed KV cache enables a 1 million token context window that’s actually usable in practice. At 1M tokens, full softmax attention would require ~1TB of KV cache memory. K3’s hybrid approach reduces this to something that fits on a single node&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-progression&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-progression&quot; aria-label=&quot;Anchor link for: the-progression&quot;&gt;The Progression&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Looking at the evolution:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;&#x2F;th&gt;&lt;th&gt;Attention&lt;&#x2F;th&gt;&lt;th&gt;Key Innovation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Linear Attention&lt;&#x2F;td&gt;&lt;td&gt;Additive state&lt;&#x2F;td&gt;&lt;td&gt;O(1) memory, but interference&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;DeltaNet&lt;&#x2F;td&gt;&lt;td&gt;Delta rule&lt;&#x2F;td&gt;&lt;td&gt;Better recoverability&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Gated DeltaNet&lt;&#x2F;td&gt;&lt;td&gt;Scalar gate&lt;&#x2F;td&gt;&lt;td&gt;Selective forgetting&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;KDA (Kimi Linear)&lt;&#x2F;td&gt;&lt;td&gt;Per-channel gate&lt;&#x2F;td&gt;&lt;td&gt;Fine-grained memory control&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;K3&lt;&#x2F;td&gt;&lt;td&gt;KDA + MLA hybrid&lt;&#x2F;td&gt;&lt;td&gt;Scale + multimodality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Each step adds capacity to address a concrete limitation in the preceding system. This isn’t “make it bigger and hope” - it’s targeted architectural improvements that compound.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-happens-after-for-text-generation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-happens-after-for-text-generation&quot; aria-label=&quot;Anchor link for: what-happens-after-for-text-generation&quot;&gt;What happens after for text generation?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Yeah, so the model actually did the job. The job of the model is to give out out probabilities. That’s it. Generally, GPT architectures and all sorts of modern LLM architectures are decode-only, so there is no real encoder. The inputs are the prompts, and it simply generates the probabilities. It has nothing to do with text generation. After that, we have to pick those tokens that the model has generated.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The attention outputs are for the input sequence that we have, that is the prefill that we have done, first of all, stored in the KV cache&lt;&#x2F;li&gt;
&lt;li&gt;then we retrieve the attention output for the last token in the input sequence&lt;&#x2F;li&gt;
&lt;li&gt;Then, to get the output weights, we make it go through a linear layer (that is, a projection layer). After which we just simply multiply the transpose of the output weights to the attention output, and we get the logits. Then we take a softmax of those logits.&lt;&#x2F;li&gt;
&lt;li&gt;only after this do we decode the token, and decoding can happen in multiple ways:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;We can do it greedily, so just picking up the token with the highest probability.&lt;&#x2F;li&gt;
&lt;li&gt;We can do some sort of sampling, so any top-k sampling in which we can pick the token from the k most likely tokens.&lt;&#x2F;li&gt;
&lt;li&gt;Any top-p decoding as well, in which we pick a token from the smallest subset of tokens such that their cumulative probability exceeds the p threshold.
A fancier way of making the models’ output more creative&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;And at last, we simply use the new token as the next input&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hybrid-attention-models-need-their-kernels&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hybrid-attention-models-need-their-kernels&quot; aria-label=&quot;Anchor link for: hybrid-attention-models-need-their-kernels&quot;&gt;hybrid attention models need their kernels&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The code example I have shared shows the naive sequential loop for clarity. In practice, you’d use chunked parallel computation (which is what flash linear attention kernels do). The sequential form is pedagogically useful but would be slow without proper kernelization.&lt;&#x2F;p&gt;
&lt;p&gt;K3 demonstrates that linear attention variants can scale to frontier model sizes when combined thoughtfully with softmax attention. The hybrid approach isn’t a compromise, it’s genuinely better than either pure approach for long-context workloads. The catch? You need the kernels. All of this efficiency is theoretical without optimized CUDA implementations. Moonshot open-sourced their KDA kernel and vLLM integration, which is why Kimi Linear actually achieves the claimed speedups in practice.&lt;&#x2F;p&gt;
&lt;p&gt;To make this clearer, a practical titbit. Qwen3.5-2B uses a hybrid architecture, some layers are full quadratic attention (standard softmax), some are linear attention (avoiding the n² computation). Sounds great for efficiency. But without the flash-linear-attention CUDA kernels installed, the linear attention layers will fall back to a naive sequential torch loop, processing tokens one by one instead of in the efficient chunked&#x2F;parallel form. The result is fuked up 5-6x worse speed loss. The linear attention layers are theoretically O(n) instead of O(n²). But the naive implementation is worse than a well-optimized O(n²) Flash Attention because Flash Attention’s tiled memory access pattern is so cache-friendly that it beats an algorithmic advantage destroyed by poor memory access patterns. algorithmic complexity means nothing without implementation quality. A well-kernelized O(n²) beats a poorly-implemented O(n) every time on real hardware. This is why Flash Attention dominates! not because quadratic is somehow better, but because &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.stanford.edu&#x2F;class&#x2F;archive&#x2F;cs&#x2F;cs224n&#x2F;cs224n.1244&#x2F;slides&#x2F;cs224n-2024-lecture18-deployment-and-efficiency.pdf&quot;&gt;Tri Dao spent years making the memory access pattern perfect for GPU cache hierarchies&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Softmax → Linear (efficiency, but interference) → DeltaNet (correction)
→ Gated (forgetting) → KDA (fine-grained) → Hybrids (best of both)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>missing writing some concurrency in Go</title>
          <pubDate>Thu, 09 Jul 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/missing-writing-go/</link>
          <guid>https://harsh-ps-2003.github.io/writes/missing-writing-go/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/missing-writing-go/">&lt;p&gt;It has been a long since I wrote Go. I still remember doing FOSS for CNCF folks and was deep in Go, until I got distracted by Rust ;)&lt;&#x2F;p&gt;
&lt;p&gt;I just saw an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;divan.dev&#x2F;posts&#x2F;go_concurrency_visualize&#x2F;&quot;&gt;awesome Go concurrency visualization&lt;&#x2F;a&gt;. So as I got some free time today, I am gonna write about some concurrency patterns in Go I saw being used in prod.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;background&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#background&quot; aria-label=&quot;Anchor link for: background&quot;&gt;Background&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;~crary&#x2F;819-f09&#x2F;Hoare78.pdf&quot;&gt;Communicating Sequential Processes&lt;&#x2F;a&gt; came, the main thing it did was making communication the foundation of concurrent programming. So, if you want to communicate with 2 processes, you should always do it using fixed defined channel, instaed of directly sharing memory. It was one of the core ideas of the paper. There were many languages born out of the paper. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;doc&#x2F;faq#csp&quot;&gt;Go’s concurrency model is influenced by Communicating Sequential Processes&lt;&#x2F;a&gt;, where independently executing processes coordinate through communication. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;ref&#x2F;spec#Channel_types&quot;&gt;Go makes channels first-class values&lt;&#x2F;a&gt;, although channels are not the only synchronization mechanism available. mutexes and atomics are also valid tools.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;goroutine                                    goroutine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    │                                            │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ▼                                            ▼&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌──────────────┐    ┌──────────────┐    ┌──────────────┐    ┌──────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  Process P1  │    │  Channel C1  │    │  Process P2  │    │  Channel C2  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└──────┬───────┘    └──────┬───────┘    └──────┬───────┘    └──────┬───────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │── Sends data ────&amp;gt;│                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │── Passes data ───&amp;gt;│                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │── Sends data ────&amp;gt;│&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │&amp;lt;───────────────── Passes data back ───│                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       │                   │                   │                   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;┌──────┴───────┐    ┌──────┴───────┐    ┌──────┴───────┐    ┌──────┴───────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;│  Process P1  │    │  Channel C1  │    │  Process P2  │    │  Channel C2  │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;└──────────────┘    └──────────────┘    └──────────────┘    └──────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;some-basics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-basics&quot; aria-label=&quot;Anchor link for: some-basics&quot;&gt;Some basics&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There is an overhead in creation&#x2F;destruction of OS threads (system calls and memory allocation) which are preemptive. They are typically ~1-2MB stack size, have expensive context switches (saves&#x2F;restores full CPU registers, kernel transition) handled by the OS kernel for small work. As we are not dealing with OS threads, instead goroutines. And goroutines (green threads are incredibly lightweight, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;src&#x2F;runtime&#x2F;stack.go#L77&quot;&gt;starting at ~2-4KB of stack space&lt;&#x2F;a&gt;) are multiplexed into multiple OS threads (usually equal to the number of CPU cores). Because the Go scheduler manages goroutines in user space, switching between them is significantly faster than a kernel-level OS thread context switch. Spawning a million goroutines is cheap relative to OS threads, very large numbers still consume stack and scheduler resources and can retain heap objects.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional OS threads have a fixed stack size. If a thread runs out of stack space, it causes a stack overflow. To prevent this, languages like Java allocate large stacks (e.g., 1MB) upfront, which limits the total number of concurrent threads you can have (usually in the thousands).
Goroutines solve this with a growable&#x2F;shrinkable segmented stack:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;They start very small (typically 2KB to 4KB).&lt;&#x2F;li&gt;
&lt;li&gt;If a goroutine needs more memory during execution, the Go runtime automatically allocates a larger segment and copies the old stack over, allowing a single program to run millions of concurrent goroutines simultaneously.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;src&#x2F;runtime&#x2F;HACKING&quot;&gt;Go uses an M:N scheduler and its scheduler is implemented as 3 structs, G, M and P&lt;&#x2F;a&gt; (all heap allocated, but are never freed, so their memory remains type stable, so the runtime can avoid write barriers in the depths of the scheduler), wherein a goroutines exists only in the virtual space of go runtime and not in the OS :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;G (simply Goroutine): Represents the goroutine and its stack. When a goroutine exits, its G object is returned to a pool of free Gs and can later be reused for some other goroutine.&lt;&#x2F;li&gt;
&lt;li&gt;M (Machine): Represents an OS thread managed by the operating system, that can be executing user Go code, runtime code, a system call, or be idle. There can be any number of Ms at a time since any number of threads may be blocked in system calls.&lt;&#x2F;li&gt;
&lt;li&gt;P (Processor): Represents the logical resource (or context) required to execute Go code, such as scheduler and memory allocator state. The number of Ps usually equals the number of CPU cores (GOMAXPROCS).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The scheduler’s job is to match up a G (the code that we want to execute), an M (where we want to execute it), and a P (the rights and resources required to execute it). When an M stops executing user Go code, for example by entering a system call, it returns its P to the idle P pool. In order to resume executing user Go code, for example on return from a system call, it must acquire a P from the idle pool.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of the OS kernel switching between thousands of heavy threads, the Go runtime efficiently schedules active goroutines across a small pool of OS threads. If a goroutine blocks (e.g., waiting for I&#x2F;O or a channel), its associated OS thread can be detached or assigned to run other ready goroutines, maximizing CPU utilization.&lt;&#x2F;p&gt;
&lt;p&gt;If a goroutine blocks on system call, it blocks it’s running thread. But another thread is taken from the waiting queue of Scheduler and used for other runnable goroutines. However, if you communicate using channels in go which exists only in virtual space, the OS doesn’t block the thread. Such goroutines simply go in the waiting state and other runnable goroutine (from the M struct) is scheduled in it’s place. Don’t communicate by sharing memory, share memory by communicating.&lt;&#x2F;p&gt;
&lt;p&gt;The go runtime scheduler also does cooperative scheduling, which means another goroutine will only be scheduled if the current one is blocking or done. This is so much better than pre-emptive scheduling which uses timely system interrupts to block and schedule a new thread as that may lead a task to take longer than needed to finish when number of threads increases, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Go through the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.columbia.edu&#x2F;~aho&#x2F;cs6998&#x2F;reports&#x2F;12-12-11_DeshpandeSponslerWeiss_GO.pdf&quot;&gt;paper&lt;&#x2F;a&gt; yourself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;worker-pools&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#worker-pools&quot; aria-label=&quot;Anchor link for: worker-pools&quot;&gt;Worker Pools&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now, worker pool allows us to reuse threads for multiple tasks.A worker pool creates a fixed set of worker goroutines. Its main purpose is to bound active work and resource consumption, it does not directly manage or reuse OS threads. to these we can push tasks. We can refer to it as thread pool as well. But, does this matter in Go? You do not really need a worker pool to save the system from the overhead of creating goroutines. So, this traditional pattern (often used in C++ or Java to avoid the heavy cost of spawning OS threads) is not strictly necessary for performance in Go in the same way it is in other languages. If we aren’t saving on thread creation costs, why use a worker pool? We use them as a resource management and throttling mechanism.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;throttling&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#throttling&quot; aria-label=&quot;Anchor link for: throttling&quot;&gt;Throttling&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine you are building a service that scrapes 10,000 URLs. If you spawn 10,000 goroutines simultaneously, you will likely:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Exhaust the file descriptors on your machine&lt;&#x2F;li&gt;
&lt;li&gt;Get banned by the target servers as you are making too many requests&lt;&#x2F;li&gt;
&lt;li&gt;Flood your database connections&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A worker pool acts as a semaphore. It limits the number of tasks running in parallel to a fixed number, ensuring that even if you have 10,000 tasks, only 20 are active at any given moment.&lt;&#x2F;p&gt;
&lt;p&gt;So, clearly there is a semaphore pattern coming!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;controlling-resource-consumption&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#controlling-resource-consumption&quot; aria-label=&quot;Anchor link for: controlling-resource-consumption&quot;&gt;Controlling Resource Consumption&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Even though goroutines are cheap, the work they might not be. If each goroutine performs a memory-intensive task (like image processing or large JSON decoding or whatever), spawning too many simultaneously will lead to an OOM. A worker pool allows you to constrain memory footprint.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;code-snippet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#code-snippet&quot; aria-label=&quot;Anchor link for: code-snippet&quot;&gt;Code Snippet&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Task represents the work to be done.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt; numWorkers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-constant&quot;&gt; numTasks&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1. Create the communication channel.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Buffered channels allow the producer to keep working even if workers &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; are slightly behind, up to the buffer limit.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	jobs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; numTasks&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2. Initialize the WaitGroup to track active workers.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3. Start the worker pool.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; w&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; w&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; numWorkers&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; w&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Increment the counter for each worker started&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		go&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;w&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; jobs&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;wg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 4. Send tasks to the workers.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; numTasks&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		jobs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 5. Close the channel to signal no more work is coming.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The range loop in the worker will terminate once the channel is &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; empty AND closed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;	close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 6. Block until all workers have finished their tasks.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;All tasks complete. Main exiting.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; worker is the function run by each goroutine.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; worker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; jobs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Task&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Ensure the worker signals it is done when the function exits.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	defer&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The &amp;#39;range&amp;#39; loop will continue until the channel is closed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; task&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; jobs&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Worker &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; started task &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; task&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;		&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Simulate heavy work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Millisecond&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 500&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Worker &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; finished task &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; task&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Worker &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shutting down&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;close(jobs)&lt;&#x2F;code&gt;: This is the most important part of the pattern. Without it, the range loop in the workers will block forever, waiting for a new task that will never arrive (a deadlock&#x2F;leak).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;sync.WaitGroup&lt;&#x2F;code&gt;: This ensures your main function does not terminate before the workers have finished processing the last items in the queue.&lt;&#x2F;li&gt;
&lt;li&gt;Worker Loop: The pattern for task := range jobs is idiomatic Go. It cleanly handles the transition from active work to termination without requiring complex conditional checks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This pattern is ideal for throttling. By changing numWorkers, you control exactly how many concurrent operations (API calls, file writes, database queries) are happening at once, preventing your system from consuming too many system resources or being rate-limited by external services.&lt;&#x2F;p&gt;
&lt;p&gt;So, you use a worker pool in Go not to save the CPU from creating threads, but to protect your application, your database, or external APIs from being overwhelmed by your own concurrency. Thats why, its concurrency pattern.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;whats-leak&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#whats-leak&quot; aria-label=&quot;Anchor link for: whats-leak&quot;&gt;Whats leak?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because in worker pools we create goroutines once and reuse it, idle workers can become problematic. An idle worker is normal while its pool is expected to remain alive. It becomes a leak when the worker should have terminated but remains permanently blocked because its shutdown or cancellation path is broken. If your code leaks goroutines, meaning you have workers hanging around waiting for tasks that will never come, your application doesn’t break in a loud, obvious way. Instead, it slowly, quietly begins to wither. No standard memory dump is gonna save your ass. And this leak will slowly compound and make your life hell.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine you have a pool of 100 workers designed to process incoming web requests. Due to a bug in your shutdown logic, every time you deploy a new version of your service or trigger a specific event, 5 of those workers fail to exit. They don’t do anything. They aren’t consuming CPU cycles, so your monitoring dashboards stay green. They are just… sitting there. They are holding onto 2KB of stack memory each. To a modern server with gigabytes of RAM, 10KB of wasted memory is nothing really. But a month later? You have thousands of these zombie goroutines. Now, your memory usage has climbed by several hundred megabytes. Your garbage collector starts working harder to track these thousands of objects. Your application gets slower, more sluggish, and eventually, the OOM killer arrives and restarts your container without warning.&lt;&#x2F;p&gt;
&lt;p&gt;Dont start panicking and looking at memory dump if this happens, use tools like pprof to visualize the goroutine blocking profile. It will show you exactly where your workers are stuck, and more importantly, it will show you that they have been sitting on that channel operation for hours, which is your indicator that they are zombies.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;semaphore-i-e-bounded-concurrency&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#semaphore-i-e-bounded-concurrency&quot; aria-label=&quot;Anchor link for: semaphore-i-e-bounded-concurrency&quot;&gt;Semaphore i.e Bounded Concurrency&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In typical usecases, we want to achieve the same throttle effect as a worker pool, but without the lifecycle management overhead (you don’t need to close channels or manage worker exit).&lt;&#x2F;p&gt;
&lt;p&gt;So for that, we can use a buffered channel as a semaphore. The size of the buffer acts as max concurrency limit.&lt;&#x2F;p&gt;
&lt;p&gt;There is no issue of idle workers here as we spawn goroutines for every task (this is a tradeoff), and they exit completely when done and the memory is reclaimed by GC. Its quite clean.&lt;&#x2F;p&gt;
&lt;p&gt;If your application processes a constant, high-volume stream of tasks, a Worker Pool is more efficient because it avoids the minor overhead of constant goroutine creation. If your application handles periodic, bursty, or ad-hoc tasks, the Semaphore Pattern is significantly cleaner, easier to maintain, and eliminates the risk of goroutine leaks.&lt;&#x2F;p&gt;
&lt;p&gt;In a traditional Worker Pool, if a worker deadlocks, you have a fixed number of stuck workers so your throughput drops to zero whihc is quite predictable and easy to monitor. In the Semaphore Pattern (where you spawn goroutines dynamically), a deadlock can be much more dangerous. New tasks will stop spawning and capacity, can lead to a complete system hang. So, never perform a task (especially one involving I&#x2F;O, network, or DB calls) without a &lt;code&gt;context.WithTimeout&lt;&#x2F;code&gt;. If a task hangs, the context will cancel, the execute function should return, and the defer will release the semaphore. You can also monitor semaphone depth, since the channel is a physical object in your memory. If &lt;code&gt;len(semaphore)&lt;&#x2F;code&gt; stays at &lt;code&gt;maxCapacity&lt;&#x2F;code&gt; for an unusually long time, you know your workers are deadlocked. You can expose this as a metric (e.g., Prometheus) to alert you that your in-flight tasks are stuck. If you seriously want to do an x-ray :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;go tool pprof http:&#x2F;&#x2F;localhost:PORT&#x2F;debug&#x2F;pprof&#x2F;goroutine&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Look for goroutines stuck in execute&lt;&#x2F;li&gt;
&lt;li&gt;Because you aren’t using a long-lived pool, you will see a bunch of identical goroutines all stuck at the exact same line of code in execute. If you see 100 goroutines all waiting on the same network call, you have found your deadlock immediately&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;things-in-action&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#things-in-action&quot; aria-label=&quot;Anchor link for: things-in-action&quot;&gt;Things in action&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In production, your service isn’t just processing a fixed list of tasks, it’s likely reading from an endless stream (like a Kafka topic). You want to process these messages in parallel to maintain high throughput, but you need to ensure that when your service receives a termination signal (like a Kubernetes SIGTERM), it doesn’t just kill the application and lose the message currently being processed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Consumer manages the ingestion and processing flow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Consumer&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Context&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; workerCount&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1. Channel to buffer messages between the reader and workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	queueChan&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	var&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sync&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WaitGroup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2. Spawn worker pool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; workerCount&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;		wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Add&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		go&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			defer&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;			&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Workers process until the channel is closed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; queueChan&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;				fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Worker &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; processing: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; msg&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;				time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;500&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Millisecond&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Simulate work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;			fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Worker &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; stopped.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3. Main consumption loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This loop pulls from the &amp;quot;stream&amp;quot; (Kafka&#x2F;Queue)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	go&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		defer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;queueChan&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Closing allows workers to finish remaining tasks and exit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			case&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Triggered by OS signal or shutdown request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;				fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Shutdown signal received, stopping ingestion...&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;				return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;			default&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Simulate reading from Kafka&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;				msg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;kafka-message-&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; time&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Now&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;15:04:05&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;				&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Attempt to send to queue; blocks if buffer is full (Backpressure)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;				select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;				case&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; queueChan&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; msg&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;				case&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;					return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;				}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	}&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 4. Graceful Shutdown Wait&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Wait here until the context triggers and the channel is closed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;	&amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ctx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Done&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	wg&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Wait for all workers to finish processing current items&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;	fmt&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;All workers finished. Clean shutdown complete.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Interesting things in code :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Cool Backpressure Management! The queueChan is buffered (e.g., make(chan string, 100)). So, if your workers are slower than the Kafka reader, the channel will fill up. Once full, the &lt;code&gt;queueChan &amp;lt;- msg&lt;&#x2F;code&gt; operation will block the producer. This forces your Kafka consumer to wait, effectively applying backpressure to the upstream system. This prevents your service from running out of memory by hoarding too many messages in the RAM.&lt;&#x2F;li&gt;
&lt;li&gt;Graceful Degradation. In production, you never want to kill a process abruptly for sure. so when service receives a SIGTERM from k8s, &lt;code&gt;ctx.Done()&lt;&#x2F;code&gt; signals the reader stops pulling new messages from Kafka, &lt;code&gt;close(queueChan)&lt;&#x2F;code&gt; sends a stop signal to all workers and the hero &lt;code&gt;wg.Wait()&lt;&#x2F;code&gt;, the main function waits for the WaitGroup. Because the channel is closed, the range loop in each worker will naturally finish processing the remaining items in the buffer and then exit gracefully.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In a real production app, you would add an &lt;code&gt;errChan&lt;&#x2F;code&gt; to catch failures from execute(task). If a worker encounters a database error, it shouldn’t just die! it should log the error and perhaps send the message to a Dead Letter Queue (DLQ) so you can replay it later without crashing the entire consumer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pipelines&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#pipelines&quot; aria-label=&quot;Anchor link for: pipelines&quot;&gt;Pipelines&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Where Worker Pools are about parallelism (doing the same task N times at once), Pipelines are about composition (doing a sequence of different tasks in stages). Each ETL stage is a separate goroutine, and they are connected by channels. Each stage has its own in-channel and out-channel.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Stage 1: Generates work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; generator&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; nums&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    go&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        defer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;out&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; nums&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            case&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            case&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; out&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Stage 2: Processes work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;chan&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    go&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; func&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        defer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; close&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;out&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; range&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            select&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            case&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; n&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            case&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;done&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; out&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is quite a gold standard in prod.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Its modular. You can test Stage 1, Stage 2, and Stage 3 independently&lt;&#x2F;li&gt;
&lt;li&gt;The gift of independent Scaling. You can have 1 “Extract” goroutine, 10 “Transform” goroutines (a worker pool within a stage), and 2 “Load” goroutines. You match the resource usage to the bottleneck of each specific stage.&lt;&#x2F;li&gt;
&lt;li&gt;Pipelining gives True Parallelism. Because stages are connected by channels, while Stage 3 is saving message A to the database, Stage 2 can be transforming message B, and Stage 1 can be fetching message C. It keeps your CPU cores busy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;fan-out-and-in&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fan-out-and-in&quot; aria-label=&quot;Anchor link for: fan-out-and-in&quot;&gt;Fan out and in!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In production, you often need to Fan-Out (start multiple workers for a slow transformation stage i.e distribute tasks to multiple goroutines for parallel processing) and Fan-In (merge those multiple results back into one channel). This combines everything :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pipeline - The structure of stages&lt;&#x2F;li&gt;
&lt;li&gt;Worker Pool - Used within a stage to process data in parallel&lt;&#x2F;li&gt;
&lt;li&gt;Semaphore&#x2F;Channel Throttling - Used to ensure the pipeline doesn’t consume more memory than allowed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;channels-as-first-class-primitives&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#channels-as-first-class-primitives&quot; aria-label=&quot;Anchor link for: channels-as-first-class-primitives&quot;&gt;Channels as first class primitives&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Because channels are values, you can pass them, store them, and send them over other channels. This allows you to treat channels as futures or promises.&lt;&#x2F;p&gt;
&lt;p&gt;In standard concurrency, ordering is rarely guaranteed because of the Go scheduler is not deterministic. When you launch Goroutines, they complete in whatever order the CPU dictates. If you need order, you have to engineer it. Its a burning question! How do I process tasks in parallel to get speed, but output the results in the exact order they arrived?&lt;&#x2F;p&gt;
&lt;p&gt;So, its awesome for ordered data streaming, but its quite fragile when managing complex state reconciliation (like k8s does)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;technicalities&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#technicalities&quot; aria-label=&quot;Anchor link for: technicalities&quot;&gt;Technicalities&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The core of this pattern lies in decoupling the order of dispatch from the timing of execution. We achieve this by establishing a strict synchronization barrier using a Channel of Channels (a &lt;code&gt;chan chan T&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;First we establish sequence. The dispatcher is responsible for two distinct operations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Orchestration - It initializes a unique resultChannel for every incoming task. This channel acts as a private synchronization point for the specific task’s lifecycle.&lt;&#x2F;li&gt;
&lt;li&gt;Sequencing - It pushes the newly created resultChannel into the procQueueChan. Because procQueueChan is a buffered or unbuffered FIFO channel, the order in which channels are inserted is preserved. This is the Serialization Phase.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each worker goroutine is decoupled from the sequencing logic. It receives its specific task and its private resultChannel. Because the runtime scheduler handles goroutine preemption and execution across M OS threads, the workers execute in parallel. The completion order is arbitrary, dependent on task complexity, I&#x2F;O wait times, and scheduler state. Crucially, the worker is not responsible for ordering, it is only responsible for executing the logic and signaling completion by writing to its assigned resultChannel.&lt;&#x2F;p&gt;
&lt;p&gt;Later we reestablish order. The Aggregator stage iterates over procQueueChan. Technically, it performs two levels of indirection: &lt;code&gt;result := &amp;lt;-(&amp;lt;-procQueueChan)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Channel Acquisition - It blocks until it receives a channel from the queue. This is the Synchronization Barrier.&lt;&#x2F;li&gt;
&lt;li&gt;Result Retrieval - Once it acquires the &lt;code&gt;resultChannel&lt;&#x2F;code&gt;, it immediately blocks on &lt;code&gt;&amp;lt;- resultChannel&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The Aggregator effectively waits for the workers in the precise order they were dispatched. If the first task (Task N) takes significantly longer to execute than Task N+1, the Aggregator will remain blocked at &lt;code&gt;&amp;lt;- resultChannel_N&lt;&#x2F;code&gt;, even if the data for Task $N+1$ has already been computed and is sitting in its own resultChannel. This creates a deterministic output stream that mirrors the input stream’s sequence.&lt;&#x2F;p&gt;
&lt;p&gt;There are thinfs to be concerned about, plenty of runtime constraints.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There can be memory pressure if you push things to scale.  You are creating N channel objects for $N$ tasks. While Go’s heap allocation for channels is efficient, in high-throughput systems (thousands of tasks per second), this increases GC pressure. Developers must tune GOGC or consider channel reuse patterns to mitigate heap fragmentation.&lt;&#x2F;li&gt;
&lt;li&gt;This pattern inherently suffers from Head-of-Line (HOL) blocking. If the first task in a sequence is computationally expensive or hangs, the entire pipeline’s output is blocked, regardless of how quickly subsequent tasks are completed.&lt;&#x2F;li&gt;
&lt;li&gt;Each worker goroutine must have a defer block that either writes to the resultChannel or closes it. Failure to send a result will cause the Aggregator to block indefinitely, leading to a permanent stall of the pipeline.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;studtying-k8s-a-bit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#studtying-k8s-a-bit&quot; aria-label=&quot;Anchor link for: studtying-k8s-a-bit&quot;&gt;Studtying k8s a bit&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Ordered Parallelism is pretty foundational concurrency pattern in k8s controller (kinda implicit Fan-Out&#x2F;Fan-In though). but K8s prefers &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;client-go&#x2F;tree&#x2F;master&#x2F;util&#x2F;workqueue&quot;&gt;Work Queues with internal locking mechanisms&lt;&#x2F;a&gt;, where key-based locking acts as the serialization barrier to ensure that parallel workers don’t corrupt the cluster state by processing events out of order. pattern manifests as :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Queue Interface: Instead of passing channels, K8s uses an interface that keeps track of the Key (e.g., namespace&#x2F;pod-name).&lt;&#x2F;li&gt;
&lt;li&gt;Deduplication: In a pipeline, if you have multiple events for the same resource (e.g., Pod “A” created, Pod “A” updated), a raw Fan-Out might send these to different workers simultaneously. Kubernetes Work Queues use deduplication based on an object’s key. This ensures that only one worker processes a specific object at any given time, which is the only way to guarantee consistency in a state machine. The workqueue internally ensures that if the same key (the same Pod) is added to the queue multiple times while a worker is processing it, the queue deduplicates those events.&lt;&#x2F;li&gt;
&lt;li&gt;Serialization: By locking on the Key (the object identifier), K8s achieves the exact same goal as Channel of Channels! It ensures that only one worker is ever processing a specific object at any given time, preserving the order of operations for that object.&lt;&#x2F;li&gt;
&lt;li&gt;Failure Recovery: Raw channels cannot “retry” an event easily. Kubernetes Work Queues provide a Requeue mechanism where a controller can signal that it failed to process an object, allowing the queue to put it back for later retries.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;the secret sauce seems to be rate limited queue :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Kubernetes must guarantee that if it receives Create Pod and then Delete Pod for the same object, it processes them in that order. If it processes “Delete” before “Create,” the controller state would be permanently broken.&lt;&#x2F;li&gt;
&lt;li&gt;To handle shit be inserted: If a specific object causes a controller to panic or error consistently, you do not want to block the entire pipeline you knww&lt;&#x2F;li&gt;
&lt;li&gt;Backoff Logic: The RateLimitingQueue tracks how many times an object has failed. If it fails, it is not immediately re-queued, the queue forces a delay (e.g., 5ms, 10ms, 20ms…) before allowing it to be processed again. This prevents a faulty object from creating a hot loop that consumes 100% of the controller’s CPU.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, in k8s, things are implicit :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Implicit Fan-Out: The workqueue doesn’t use a Channel of Channels to distribute work, instead, you, as the developer, define N worker goroutines that all call queue.Get() on the same workqueue instance. This is the Worker Pool pattern. It effectively performs the Fan-Out by allowing multiple workers to pull from the central queue in parallel.&lt;&#x2F;li&gt;
&lt;li&gt;No Fan-In Required: Because the workers update the Kubernetes API Server directly (the Source of Truth), there is no need to merge results back into a single channel. The API server acts as the final aggregator for the system’s state.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;ultimately, K8s is a distributed system that must achieve eventual consistency. This concurrency pattern is chosen for two specific reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Isolation: If a worker processing a Pod event panics or hangs, it doesn’t stop the workers processing Node or Service events. The queue ensures the controller stays responsive.&lt;&#x2F;li&gt;
&lt;li&gt;Ordered Reconciliation: The cluster state is essentially a giant fucking state machine. You cannot reconcile a Pod’s status if you don’t process the events that led to its current state in order obviosuly. This pattern gives K8s the ability to scale to thousands of Pods (parallelism) while keeping the API server state consistent (ordering).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;but-dont-you-like-rust&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-dont-you-like-rust&quot; aria-label=&quot;Anchor link for: but-dont-you-like-rust&quot;&gt;But dont you like Rust?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Yea. Its philosophical. You might not have a great first impression of it, but often the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deepu.tech&#x2F;my-second-impression-of-rust&#x2F;&quot;&gt;second impression of Rust is nice&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You know what happens when a goroutine panics while holding a standard Go sync.Mutex? Go begins unwinding the call stack for that specific goroutine, executing any defer statements along the way. If you followed idiomatic Go and placed defer mu.Unlock() immediately after locking, the deferred function will execute during stack unwinding, releasing the mutex so other goroutines don’t deadlock. Unless caught, the panic will travel up to the goroutine’s root, crash the entire Go program, and print a stack trace. You like this? the &lt;code&gt;recover()&lt;&#x2F;code&gt; will only works if called directly inside a deferred function. There are isolation troubles as well. a panic in one goroutine does not automatically crash other goroutines, it only crashes the entire program if the panic happens on a goroutine that doesn’t recover it (with the exception of the main goroutine). If Worker A panics and recovers using defer + recover(), Worker B and Worker C keep running uninterrupted. However, because Go doesn’t poison mutexes, if Worker A left the shared data structure in a half-modified, broken state before panicking, Worker B will successfully acquire the lock and read that corrupted data without any warning from the runtime. I dont like this. Go trusts you. If a panic happens, the lock opens, but the data is unverified.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Lack of Compile-Time Thread Safety - Unlike Rust with rigorous ownership models, Go’s compiler does not prevent data races at compile time. Standard types (like maps and slices) are unprotected. Concurrency errors, such as concurrent map writes or race conditions, are frequently discovered only at runtime—either via tests, the runtime race detector, or sudden 2AM production crashes.&lt;&#x2F;li&gt;
&lt;li&gt;Silent Data Corruption via Unpoisoned Mutexes - GGo has no concept of mutex poisoning. A Go mutex is completely agnostic to panics. If a goroutine panics, the mutex unlocks (assuming you used defer), but it remains completely valid and available for other goroutines to lock immediately. Go assumes that if you recover from the panic, the shared data is fine, or it’s your responsibility to clean up any corrupted state&lt;&#x2F;li&gt;
&lt;li&gt;Goroutine Leaks - Because spawning a goroutine is as simple as prefixing a function call with the go keyword, it is easy to spawn tasks that block indefinitely on unbuffered channels or missing context cancellations. These leaked goroutines persist in memory for the lifetime of the application, gradually degrading performance without an immediate compiler or runtime warning.&lt;&#x2F;li&gt;
&lt;li&gt;Deadlock Vulnerabilities - While Go’s runtime can detect simple deadlocks (e.g., all goroutines sleeping forever), complex deadlocks involving channels, select statements, and external resource locks often go undetected by the runtime. Debugging blocked channels or circular dependencies in large Go codebases is fucked up&lt;&#x2F;li&gt;
&lt;li&gt;Abstracted Scheduling Control - Go’s M:N scheduler handles goroutine multiplexing onto OS threads automatically. While convenient, this abstraction gives developers very little direct control over OS thread pinning, CPU affinity, or low-level thread scheduling priorities, which can be a limitation for ultra-low-latency systems&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;now-that-i-started-discussing-about-mutex-poisoning&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#now-that-i-started-discussing-about-mutex-poisoning&quot; aria-label=&quot;Anchor link for: now-that-i-started-discussing-about-mutex-poisoning&quot;&gt;Now that I started discussing about MUtex Poisoning&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If a thread panics while holding a standard standard library Mutex (typically wrapped in an Arc&amp;lt;Mutex&lt;T&gt;&amp;gt;), Rust does not leave the mutex open and silent. When the thread panics, its stack unwinds, and the RAII MutexGuard goes out of scope and is dropped. During this drop, Rust’s Mutex detects that the thread holding the lock panicked. It automatically poisons the mutex. The mutex is marked as poisoned because the data it protects may have been left in a half-modified, inconsistent state when the panic hit. Unlike Go, where another thread can immediately grab the unlocked mutex and read potentially corrupted data, Rust refuses to let you blindly trust the data. When another thread tries to call .lock() on a poisoned mutex, it receives a PoisonError instead of the normal data. Rust forces you (via the type system and Result handling) to explicitly choose how to handle the poisoned state before you can access the inner data. You have to handle the Err variant of the lock result, preventing silent data corruption.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Mutex&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data_clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; guard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data_clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        guard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Something went wrong mid-modification!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Panic while holding lock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Wait for thread to panic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Next thread tries to acquire the lock:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Data: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;poisoned&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Rust caught the panic! The data might be corrupted.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We can access the inner data via the poison error if we want to recover it:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; guard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; poisoned&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;into_inner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Recovered from poisoned mutex. Potentially inconsistent data: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;guard&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This shows you how languages differ philosophically. Go’s Philosophy to me is Simplicity and Trust. Go gives you lightweight primitives (goroutines, channels, sync.Mutex) and assumes you, as the developer, will write the correct orchestration code. It trusts that if a panic occurs, you’ve handled it with recover() and cleaned up your data structures. It prioritizes runtime performance and flexibility, meaning it won’t inject hidden overhead to track the health of every single lock. Rust’s Philosophy could be Fearless Concurrency via the Type System. Rust assumes that any shared mutable state is a potential bug factory, and threads will panic unpredictably. Therefore, Rust builds safety checks directly into the compiler and types (Send, Sync, MutexGuard, PoisonError). It forces you to deal with failure states (like a poisoned mutex) at compile time or via explicit error handling, making silent data corruption much harder to achieve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-is-better-in-the-agentic-world&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rust-is-better-in-the-agentic-world&quot; aria-label=&quot;Anchor link for: rust-is-better-in-the-agentic-world&quot;&gt;Rust is better in the Agentic world&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I personally feel &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ugUeZ8-b-u0?si=7n1hdzUmoj1KJ8J1&quot;&gt;writing Rust with agents is just a better experience, its ideal for vibe coding&lt;&#x2F;a&gt;. The compiler acts as an automated reviewer, it eliminates entire classes of bugs at compile time. AI agents frequently struggle with multi-threading synchronization because reasoning about concurrent state across multiple files is difficult for LLMs. Rust’s type system prevents the AI from accidentally creating data races or unsafe shared-state concurrency.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=q9xD36NCtZ8&quot;&gt;Rust is built different!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>i should have paid a closer look at tokenizer</title>
          <pubDate>Sat, 30 May 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/i-should-have-paid-a-closer-look-at-tokenizer/</link>
          <guid>https://harsh-ps-2003.github.io/writes/i-should-have-paid-a-closer-look-at-tokenizer/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/i-should-have-paid-a-closer-look-at-tokenizer/">&lt;p&gt;Well, I gave an interview sometime ago, and wasn’t able to explain tokenizer properly, missed some points on tokenizer training, and got the sweet rejection I deserved (along with some great advices). But, I got an interested in tokenizer because of that, and damnn I found insights that I didn’t have maturity to see when I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openai&#x2F;tiktoken&quot;&gt;tiktoken&lt;&#x2F;a&gt; for the first time in my 2nd year. So going back the basics.&lt;&#x2F;p&gt;
&lt;p&gt;Everything is token in the model utopia we are living in! The API’s are priced per token. The fewer tokens required to represent an output, the faster will be the inference. Clearly it’s crucial to understand this token mumbo-jumbo.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tokenization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tokenization&quot; aria-label=&quot;Anchor link for: tokenization&quot;&gt;Tokenization&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Well, clearly the LLM cannot read English. ML models take in vectors, not weird shit like language. So, tokenizer is the bridge from English input to numbers which LLM can understand. It processes every punctuation, spaces, everything, and converts it into a sequence of integer (in a fixed range i.e. vocabulary) before the model can actually process it. The integers to vectors is embeddings. The jargon here is one-hot encodings. We map eg numbers from 1 to 100, to a 100-dim vector, with a 1 in the kth position, 0 everywhere else. Key intuition is that one-hot encodings let you think about each integer independently - useful when integers = labels. We are baking in structure to models.&lt;&#x2F;p&gt;
&lt;p&gt;Dimensions = things that vary independently. Each input has its own dimension, so each
input can be thought of independently, we don’t bake in any relation. And, the lookup table (the embedding matrix), is simply multiplying matrix with one-hot encoded vector. Softmax just converts vector to probability distribution.&lt;&#x2F;p&gt;
&lt;p&gt;This conversion matters as it bakes assumptions into the LLM that cannot be undone later. If we don’t have this correctly, the LLM will waste its capacity in encoding common words into multiple tokens, so it decides the utility of the context window.&lt;&#x2F;p&gt;
&lt;p&gt;It’s the process during which a piece of text is broken down into smaller pieces, tokens, by a tokenizer. These tokens are then assigned integer values (i.e. token IDs) which uniquely identify the tokens within the tokenizer vocabulary (set of all possible tokens used in the tokenizer training),  they essentially indexes into the tokenizer vocabulary. Just as a side note, tokenizer training is different from neural network training. You can train your own tokenizer and restrict its token space by various parameters, including the size of the vocabulary. What do you think  happens if any of the tokens in your text do not exist in the tokenizer’s vocabulary of the LLM you are trying to use? disaster. so most LLM vocabularies are pretty huge. tokenization can be of 3 main groups :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;word - splits text based on empty space characters and punctuation, etc, which is just too big of a vocabulary! can’t really create a separate token for every possible word in a language. and adding variations on top of it is just nightmarish. too much of vocabulary to manage.&lt;&#x2F;li&gt;
&lt;li&gt;character - splits text into individual characters, sometimes even punctuation. using individual characters look simple, vocabulary (256 ASCII) is tiny as well, but the problem is that this massively extends our own input sequence and doesn’t really have any structure. The model has to learn that the characters together mean a word which would burn the attention capacity. And as a transformer model has computational costs that goes quadratically with the sequence length (the attention layer compares every token with every other token), this is actually pretty expensive. Efficient-attention variants can reduce this, but the basic lesson still holds&lt;&#x2F;li&gt;
&lt;li&gt;subword - its the sweet spot. The common words stay whole and the rare words decompose into subword tokens that might seem like gibberish. Here, vocabulary also remains manageable, and the sequence also stays relatively short. We don’t really need to care much about the unknown tokens because any word can now be built from the sub-word pieces. LLMs use this&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;docs&#x2F;transformers&#x2F;en&#x2F;tokenizer_summary&quot;&gt;BPE, Unigram, Wordpiece, etc all sorts of them exist&lt;&#x2F;a&gt;. You can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;learn&#x2F;llm-course&#x2F;en&#x2F;chapter6&#x2F;8&quot;&gt;try building it&lt;&#x2F;a&gt; and play with a small model like MiniLM locally. If you play with emojis, you will see that if your token doesnt exist in the tokenizer vocabulary it gets tokenized as a special character.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bpe-the-hero-of-every-llm&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bpe-the-hero-of-every-llm&quot; aria-label=&quot;Anchor link for: bpe-the-hero-of-every-llm&quot;&gt;BPE: the hero of every LLM&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1508.07909&quot;&gt;BPE was introduced for neural MT partly to handle rare and unknown words by representing them as subword sequences rather than requiring a huge word vocabulary&lt;&#x2F;a&gt;. Byte-level BPE goes further, GPT-2-style tokenizers can represent arbitrary bytes, so the failure is usually not “unknown token,” but fragmentation, inefficient representation, strange byte pieces, or distribution shift.&lt;&#x2F;p&gt;
&lt;p&gt;It’s just a greedy compression algorithm which is sort of re-worked for tokenization. It starts small and builds up intelligently. It starts with initializing the vocabulary with 256 byte values. It tries to find a pattern by counting how often each pair of adjacent tokens appears in the training data and then merges the most common pairs. That is, it takes the most frequent pair and adds it to the vocabulary as a new token, and then it keeps on repeating until a desired vocabulary size is reached. This simply means, obviously, that the most common sequences get their own tokens while the rare ones remain split into multiple pieces. It really adapts to the specific training data set. It really has some esoteric shit if you seee &lt;code&gt;reference_gpt2.tokenizer.vocab.items()&lt;&#x2F;code&gt;. It’s a fking headache. Whethre things begin with capital letters, or space matters. Arithmetic is total mess. length is inconsistent, common numbers appears more. I am hella impressed how GPT is even able to do addition!&lt;&#x2F;p&gt;
&lt;p&gt;There are some interesting tricks in here as well :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pre-tokenization - it is possible that we get weird, awkward tokens by merging across logical boundaries. For an example, merging the period at the end with the word itself will create tokens that reduce the model’s flexibility. Pre-tokenization solves this by first splitting the text into logical units, which are usually the words or the punctuation, and then running the algorithm over these boundaries only. This gives us logical segregation of the tokens. And also this gives us a computational advantage because instead of counting the pairs across the entire corpus, now we can count how many times each unique word appears and then run the pair counting only once per that unique word. Then we could simply multiply the pair count by the word’s frequency.&lt;&#x2F;li&gt;
&lt;li&gt;Caching - obviously, this algorithm will be painfully slow on very large data sets. With each merge, we would require re-scanning the entire data set to update the statistics. It’s stupid for very large data sets, so we can just do some caching with HashMaps. We can have a bi-directional HashMap, which is:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;which pairs exist in each token&lt;&#x2F;li&gt;
&lt;li&gt;which token contains each pair
When we merge a pair, we only update the tokens containing that specific pair rather than re-scanning everything&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;Parallelization - the merging step clearly depends upon a global statistic, which is clearly hard to parallelize, but the initial counting of tokens can be very easily parallelized. By splitting the corpus into chunks and counting the token frequencies independently and then merging the counts, we can easily leverage multiple CPU cores to speed up the tokenizer training.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Despite all sorts of elegance, there are some quirks to be aware of as well :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It might be possible that those rare words get split into so many small pieces, that it potentially loses all possible semantic coherence&lt;&#x2F;li&gt;
&lt;li&gt;The same word can be tokenized differently depending upon the context&lt;&#x2F;li&gt;
&lt;li&gt;Obviously, the model can struggle with words that were extremely rare or completely absent in the tokenizer’s training data&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;embeddings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#embeddings&quot; aria-label=&quot;Anchor link for: embeddings&quot;&gt;Embeddings&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Tokenizers were developed to do complicated numerical analysis of texts, mostly based on frequencies of individual tokens in a given text. What we need is context, to somehow capture the relationships between the tokens in the text to preserve the meaning of the text, and embeddings (vectors representing tokens) are better for that. Embeddings are byproduct of transformer training and are actually trained on the heaps of tokenized texts. Embeddings are what is actually fed as the input to LLMs when we ask it to generate text. Both the encoder and decoder accept embeddings as their input and the output of the encoder are also embeddings which are then passed into the decoder’s cross-attention head which plays a fundamental role in generating (predicting) tokens in the decoder’s output. The token IDs are used to fetch the embeddings from the embeddings matrix which are then assembled into a tensor which is then fed to the input of the transformer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-model-training-chronicles&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-model-training-chronicles&quot; aria-label=&quot;Anchor link for: the-model-training-chronicles&quot;&gt;The Model training chronicles&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You give it a bunch of text, and train it to predict the next token, autoregressive magic.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;raw text &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ tokenizer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;token IDs &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ embedding table lookup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;token embeddings + positional embeddings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ transformer blocks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;contextual hidden states&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ output projection &#x2F; LM head&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logits (one for each input token) over vocabulary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ softmax&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;probability distribution over next token&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ↓ &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;convert to token and then append this to the input + run again to generate more text&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;in code :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;nn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; nn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;nn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;functional&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span&gt; F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;batch_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;seq_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vocab_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 50_000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;d_model&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 768&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;token_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;randint&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; vocab_size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;batch_size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; seq_len&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;token_embedding&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Embedding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;vocab_size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_model&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;position_embedding&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Embedding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;seq_len&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; d_model&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;positions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; torch&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;arange&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;seq_len&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; token_embedding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;token_ids&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; position_embedding&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;positions&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Each position produces a distribution over the next token.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; transformer processes this x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;token_ids&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [4, 8]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;          #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [4, 8, 768]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lm_head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Linear&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;d_model&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; vocab_size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hidden_states&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; pretend this came out of the transformer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logits&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; lm_head&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;hidden_states&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;logits&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;shape&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [4, 8, 50000]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; For training, the target is usually the same sequence shifted left:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;input_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  =&lt;&#x2F;span&gt;&lt;span&gt; token_ids&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; :&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;target_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; token_ids&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Importantly, if you give a model 100 tokens in a sequence, it predicts the next token for each prefix, ie it produces 100 predictions. This is kinda weird but it’s much easier to make one that does this. And it also makes training more efficient, because you can 100 bits of feedback rather than just one. weirdness is that 99 should be trivial, as you have already ttold what the next tokens are. the magic is because of causal attention, the representation at position 2 cannot look at tokens after position 2. During training, we pass the whole sequence in parallel, but the causal mask prevents cheating. The core thing is that it can only move information forwards in the sequence. The prediction of what comes after token 50 is only a function of the first 50 tokens, not of token 51.&lt;&#x2F;p&gt;
&lt;p&gt;For attention weights :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Q expresses what each token needs to know from others&lt;&#x2F;li&gt;
&lt;li&gt;K encodes the information that each token brings&lt;&#x2F;li&gt;
&lt;li&gt;V stores the actual content that each token shares when attended to&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;QK^T^ is the attention score that tells how well each token matches the keys of the other tokens (similarity). And then we attach corresponding V based on relevance. So, if two attention score are pretty similar, we attach more V. This is attention weights. Later the attention weights are multiplied with feed forward weight matrix so that the model has a chance to capture additional interactions across the sequence.&lt;&#x2F;p&gt;
&lt;p&gt;In multi-head, just divide the embedding dimensions with number of heads. All of them see the full input sequence, but there subset of embedding dimensions, with its own Q,K,V weights. So, the attension calculation is paralleled among heads. Nothing to do with more cores or something. it’s just that each each can focus on subset of embedding space, picking up specific patterns and relationships.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Tokenizer:      text → integers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Embedding:      integers → vectors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Transformer:    vectors → contextual vectors&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LM head:        contextual vectors → token probabilities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Conclusively, transformers are sequence operation models, they take in a sequence, do processing in parallel at each position, and use attention to move information between positions (prior positions in the sequence to the current token)! once attention has moved relevant information to a single position in the residual stream, MLPs can actually do computation, reasoning, lookup information, etc. what is going on inside MLPs?! See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;transformer-circuits.pub&#x2F;2022&#x2F;toy_model&#x2F;index.html&quot;&gt;Toy Model of Superposition Paper&lt;&#x2F;a&gt; for more on why this is hard. as said by Neil nanda, linear map → non-linearity -&amp;gt; linear map is the most powerful force in the universe and can approximate arbitrary functions. Idk man it just works!!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tokenizer-is-an-architecture-decision&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-tokenizer-is-an-architecture-decision&quot; aria-label=&quot;Anchor link for: the-tokenizer-is-an-architecture-decision&quot;&gt;The tokenizer is an architecture decision&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A tokenizer feels external because it is trained before the model. But after training starts, it becomes part of the model contract. The embedding table is indexed by token IDs. The model learns patterns over those IDs. The context window is measured in those IDs. The training budget is consumed by those IDs. The inference bill is charged by those IDs.&lt;&#x2F;p&gt;
&lt;p&gt;So tokenizer choice affects:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;training efficiency&lt;&#x2F;li&gt;
&lt;li&gt;inference cost&lt;&#x2F;li&gt;
&lt;li&gt;effective context length that the model can handle&lt;&#x2F;li&gt;
&lt;li&gt;memory usage&lt;&#x2F;li&gt;
&lt;li&gt;Generalization to unusual or out-of-vocabulary words&lt;&#x2F;li&gt;
&lt;li&gt;numeric reasoning&lt;&#x2F;li&gt;
&lt;li&gt;code modeling&lt;&#x2F;li&gt;
&lt;li&gt;RAG chunk sizes&lt;&#x2F;li&gt;
&lt;li&gt;retrieval behavior&lt;&#x2F;li&gt;
&lt;li&gt;safety filters&lt;&#x2F;li&gt;
&lt;li&gt;debugging complexity&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Changing the tokenizer is therefore not a harmless preprocessing change. It changes the model’s input language. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2402.01035v2&quot;&gt;tokenizer training data, vocabulary size, and pre-tokenization regex can affect compression, generation speed, effective context size, memory usage, and downstream code performance&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tokenization-also-decides-who-pays-more&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tokenization-also-decides-who-pays-more&quot; aria-label=&quot;Anchor link for: tokenization-also-decides-who-pays-more&quot;&gt;Tokenization also decides who pays more&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aclanthology.org&#x2F;2023.emnlp-main.614.pdf&quot;&gt;Tokenization is not uniform across languages&lt;&#x2F;a&gt;. The same amount of meaning can require very different token counts depending on the language, script, and tokenizer training data. That affects cost, latency, and sometimes quality.&lt;&#x2F;p&gt;
&lt;p&gt;For API users, this means tokenization can create hidden pricing differences. For model builders, it means tokenizer training data should be evaluated across the languages and scripts the model is expected to serve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;your-rag-depends-on-it-actually&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#your-rag-depends-on-it-actually&quot; aria-label=&quot;Anchor link for: your-rag-depends-on-it-actually&quot;&gt;Your RAG depends on it actually&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In the RAG pipeline, the text is first tokenized, then its embeddings are obtained for each token via ID, then assemble the embedding tensor, then fed into the transformer where the attention magic happens. Earlier, I used to think about RAG pipelines from the embeddings, from the chunking, but I never used to think about tokenizers. Now, you should easily be able to see, missing words in the tokenizer vocabulary can produce undesirable tokens, which has implications on RAG.&lt;&#x2F;p&gt;
&lt;p&gt;In old word-level systems, out-of-vocabulary words were a direct problem. In modern subword and byte-level tokenizers, the usual problem is different: the tokenizer can still represent the string, but it may represent it badly. A rare word, weird Unicode sequence, emoji, typo, long number, or domain-specific identifier may explode into many tokens, get normalized strangely, or produce a token sequence that the model rarely saw during training.&lt;&#x2F;p&gt;
&lt;p&gt;Easiest example is of emojis when tokenizers don’t handle it well. Even if you add contrasting emojis to the same sentence, when you embed it and then display and then see the embedding matrices along with the text where we replace the emojis with textual descriptions, you will see that the embeddings for both the emojis, even though they may mean very different things, are very close. Another case could be of misspelled words being picked correctly, or managing date and time like “It was delivered some-time ago”, who knows that sometime ago? the models generally handle cases like these with the help of additional context and chunking with metadata properly, but if your agent doesn’t confirm the specific date, i.e. any sort of time context is missing, all the best. you can literally try introducing typos into the dates or even empty space characters and wreak more havoc.&lt;&#x2F;p&gt;
&lt;p&gt;Sooo, a little bit of cleaning of input text actually go a long way, standardise the format your dates so they’re consistent throughout your embeddings, remove trailing spaces wherever you can, the same goes for any other numerical data like prices in different currencies, whatever. bloody hell there can be adversarial attacks based on word perplexities!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tokenizer-catches-you-off-guard&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tokenizer-catches-you-off-guard&quot; aria-label=&quot;Anchor link for: tokenizer-catches-you-off-guard&quot;&gt;tokenizer catches you off-guard&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A tokenizer looks like preprocessing, but in a real large-scale model training pipeline it is closer to infrastructure actually. It sits before the model, before the loss, before the dataloader emits tensors, before evaluation, and before inference. If it is wrong, the rest of the stack can be perfectly engineered and still behave strangely. it is part of the model architecture, the data pipeline, the compute budget, and sometimes the failure mode. it can catch you off-guard.&lt;&#x2F;p&gt;
&lt;p&gt;When a training run fails at the same step again and again, and the instinct is often to look at the optimizer, checkpoint, distributed setup, GPU memory, mixed precision, dataloader, etc. But if skipping one exact data step avoids the crash, the search space collapses. Now it is not “the training run is broken.” It is “this example, or this batch, or this transformation of the data is broken.” That transformation includes the tokenizer. so, when a training run fails deterministically at the same data step, we do not need to debug the whole universe, just isolate :&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Can the same checkpoint train on the next batch?&lt;&#x2F;li&gt;
&lt;li&gt;Can the same batch tokenize offline?&lt;&#x2F;li&gt;
&lt;li&gt;Does the crash disappear if the tokenizer is swapped?&lt;&#x2F;li&gt;
&lt;li&gt;Does the crash disappear if the raw document is removed?&lt;&#x2F;li&gt;
&lt;li&gt;Does the crash disappear if multiprocessing tokenization is disabled?&lt;&#x2F;li&gt;
&lt;li&gt;Does the tokenized sequence have extreme length, weird special tokens, replacement characters, or abnormal numeric runs?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The raw document is not what the transformer sees. The transformer sees token IDs. Before that happens, the system performs normalization, pre-tokenization, subword segmentation, special-token insertion, truncation, packing, batching, and tensorization:&lt;&#x2F;p&gt;
&lt;p&gt;raw text → normalization → pre-tokenization → subword segmentation → token IDs → packing&#x2F;truncation → batch tensors → model&lt;&#x2F;p&gt;
&lt;p&gt;A pathological raw string can become a pathological tokenization problem. Extremely long numeric sequences, repeated characters, weird Unicode, broken markup, logs, base64 blobs, corrupted JSON, or domain-specific identifiers can produce unusually long token sequences or trigger slow paths in tokenizer implementations. At small scale this looks like a bad row, but at pretraining scale it looks like a deterministic crash that costs hefty real money to reproduce.&lt;&#x2F;p&gt;
&lt;p&gt;This is also why tokenizer choice affects model quality, not only runtime. The tokenizer decides the atomic symbols the model learns over. If the tokenizer represents numbers, code, dates, identifiers, or non-English text poorly, the model has to spend capacity learning around that representation. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2402.01035v2&quot;&gt;the tokenizer size, pre-tokenization regex, and tokenizer training data can materially affect generation speed, effective context size, memory usage, and downstream performance&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Before launching an expensive run, I would want a tokenizer report over a representative data sample:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;tokens per character&lt;&#x2F;li&gt;
&lt;li&gt;tokens per byte&lt;&#x2F;li&gt;
&lt;li&gt;tokens per document&lt;&#x2F;li&gt;
&lt;li&gt;p50&#x2F;p95&#x2F;p99&#x2F;max tokenized length&lt;&#x2F;li&gt;
&lt;li&gt;longest numeric run&lt;&#x2F;li&gt;
&lt;li&gt;longest repeated-character run&lt;&#x2F;li&gt;
&lt;li&gt;Unicode normalization changes&lt;&#x2F;li&gt;
&lt;li&gt;replacement-character count&lt;&#x2F;li&gt;
&lt;li&gt;unknown-token count, if the tokenizer can emit unknowns&lt;&#x2F;li&gt;
&lt;li&gt;special-token leakage&lt;&#x2F;li&gt;
&lt;li&gt;encode&#x2F;decode round-trip failures&lt;&#x2F;li&gt;
&lt;li&gt;tokenization latency p50&#x2F;p95&#x2F;p99&#x2F;max&lt;&#x2F;li&gt;
&lt;li&gt;documents that timeout or tokenize abnormally slowly&lt;&#x2F;li&gt;
&lt;li&gt;compression rate by domain, language, file type, and data source&lt;&#x2F;li&gt;
&lt;li&gt;examples with extreme token&#x2F;character ratios&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At small scale, tokenizer bugs are annoying. At large scale, they are hella expensive. A failed experiment is not just a stack trace, it is GPU time, queue time, researcher time, and uncertainty. The expensive part is often not the bug itself, but the size of the search space. Was it the data? tokenizer? packing? distributed loader? checkpoint? optimizer? precision? kernel? scheduler? The right move is to reduce the search space as aggressively as possible. If changing the data fixes it, debug the data path. If swapping the tokenizer fixes it, debug the tokenizer. If disabling packing fixes it, debug sequence construction. If the same raw sample reproduces the failure offline, turn that sample into a regression test.&lt;&#x2F;p&gt;
&lt;p&gt;Generally I suspect the tokenizer when:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;training crashes deterministically on the same data step&lt;&#x2F;li&gt;
&lt;li&gt;skipping one batch avoids the failure&lt;&#x2F;li&gt;
&lt;li&gt;tokenization hangs or is much slower for a few documents&lt;&#x2F;li&gt;
&lt;li&gt;loss is worse than expected after everything else looks normal&lt;&#x2F;li&gt;
&lt;li&gt;evals regress after changing the tokenizer, normalizer, or pre-tokenization regex&lt;&#x2F;li&gt;
&lt;li&gt;numeric, code, multilingual, emoji, or log-heavy data performs unusually badly&lt;&#x2F;li&gt;
&lt;li&gt;context length seems shorter than expected in real text&lt;&#x2F;li&gt;
&lt;li&gt;a domain-specific corpus becomes much longer in tokens than in characters&lt;&#x2F;li&gt;
&lt;li&gt;a model repeats or mishandles special tokens&lt;&#x2F;li&gt;
&lt;li&gt;encode&#x2F;decode round-trip tests fail&lt;&#x2F;li&gt;
&lt;li&gt;tokenizer multiprocessing behaves differently from single-process tokenization&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A tokenizer with a good average can still have awful tails. The tails are what crash training, waste context, inflate cost, or poison batches. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huggingface&#x2F;tokenizers&#x2F;issues&#x2F;187#issuecomment-635692450&quot;&gt;there have been real tokenizer implementation issues involving hangs in subprocess&#x2F;dataloader settings, so tokenizer latency and multiprocessing behavior are not purely theoretical concerns&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;numbers-are-not-just-text&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#numbers-are-not-just-text&quot; aria-label=&quot;Anchor link for: numbers-are-not-just-text&quot;&gt;Numbers are not just text&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Numbers look simple to humans, but tokenizers often represent them in unnatural ways. One model may split a number digit by digit. Another may group it into two-or three-digit chunks. Another may tokenize from left to right, which is awkward for arithmetic because carries usually propagate from the right.&lt;&#x2F;p&gt;
&lt;p&gt;This matters because the model does not receive the number as a number. It receives a sequence of token IDs. The representation can change the difficulty of the task. A date, price, timestamp, account ID, version string, latitude-longitude pair, or long integer can become many tokens with weak numerical structure. So for numeric-heavy domains, tokenizer evaluation should include numeric stress tests as well.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2402.14903&quot;&gt;Obviously, right-to-left number tokenization can substantially improve arithmetic performance compared with standard left-to-right chunking&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The tokenizer is easy to ignore because it sits before the glamorous part of the model. But the model never sees text. It sees token IDs. That means tokenizer mistakes become model mistakes, training inefficiencies, retrieval misses, cost inflation, safety gaps, and sometimes deterministic crashes.&lt;&#x2F;p&gt;
&lt;p&gt;So the practical lesson is simple: when debugging model behavior, do not stop at the neural network. Look at the thing that decides what the neural network is allowed to see.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>cutting that inference cost</title>
          <pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/cutting-that-inference-cost/</link>
          <guid>https://harsh-ps-2003.github.io/writes/cutting-that-inference-cost/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/cutting-that-inference-cost/">&lt;p&gt;Who doesn’t want lightning fast AI responses? You don’t really want to serve responses slower than human typing speeds. Inference is hard. And, it’s not a model problem, it doesn’t differentiate between 1 and 1M requests, its scheduling problem, revolving back to depths of engineering.&lt;&#x2F;p&gt;
&lt;p&gt;When the model is downloaded, we get list of artifacts, and using those ingredients and recipe we make inference out of it. Depending on what inference engine we use (vLLM, SGLang, TensorRT), they have different ways to load and serve the model. The biggest file (atleast in case of Gemma 4 that I downloaded) was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;safetensors&#x2F;safetensors&quot;&gt;model.safetensors&lt;&#x2F;a&gt; which actually holds the model weights (it’s a bloody large JSON file). The config.json has models entire architecture (like number of attention heads, number of layers, what kind of attention, size of vocabulary, etc).  The inference engine takes the artifacts and put them to GPU (cudamemcpy shit). so lamma is pretty fast. vLLM can take some minutes as it compiles the model, a large import overhead and also a much heavier initialization for better scheduling and concurrency (important for the pre-filled decoding and the serving part). vLLM is pretty cool as it has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2309.06180&quot;&gt;PagedAttension which is adopted from OS&lt;&#x2F;a&gt; so it boasts nearly zero memory waste.&lt;&#x2F;p&gt;
&lt;p&gt;In lamma.cpp, they use mmap (OS manages the memory by holding weights in SSD and keeping track of its pointer location in RAM). When weights are needed by inference engine, it’s loaded lazily. So suppose we have Gemma 4 (its 15gb in size when I saw it), and we have a 32 GB RAM, then over PCIe  (7 GB&#x2F;s), so you can imagine loading will be in sec latency. GPU does most matmul, tensor stuff, so RAM needs to push the weights higher up memory hierarchy which is generally faster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cameronrwolfe.substack.com&#x2F;p&#x2F;decoder-only-transformers-the-workhorse&quot;&gt;Modern generative models are decoder-only&lt;&#x2F;a&gt; as :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Next-Token Prediction - Decoder-only models are structurally optimized for autoregressive text generation&lt;&#x2F;li&gt;
&lt;li&gt;Seamless Context - Instead of using an encoder to process a prompt and a decoder to respond, decoder-only models handle both by treating your prompt as the beginning of the sequence and simply letting the model continue writing&lt;&#x2F;li&gt;
&lt;li&gt;Better Scaling - Empirical evidence and industry scaling laws (like those that built GPT models) have shown that decoder-only models scale incredibly well in performance as you increase their parameters and training data&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Typical GPT-2 decoder-only architecture :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tok_emb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transformer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;wte&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;idx&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; token embeddings of shape (b, t, n_embd)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pos_emb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transformer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;wpe&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pos&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; position embeddings of shape (t, n_embd)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transformer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;tok_emb&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; pos_emb&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; block&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transformer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;h&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;transformer&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ln_f&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;logits&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lm_head&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; logits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A zoomed in transformer block :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;nn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;Module&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; __init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; config&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;__init__&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ln_1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; LayerNorm&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_embd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bias&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bias&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;attn&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; CausalSelfAttention&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ln_2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; LayerNorm&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;n_embd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bias&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bias&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mlp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; MLP&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; forward&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;attn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ln_1&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mlp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ln_2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;anistropy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#anistropy&quot; aria-label=&quot;Anchor link for: anistropy&quot;&gt;Anistropy&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Soo, a decoder-only transformer’s layers serve different purposes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Early layers are for building local features syntax, positional patterns, n-gram statistics. Too raw for task-level understanding.&lt;&#x2F;li&gt;
&lt;li&gt;Middle layers are for semantic composition. This is where the model builds a holistic representation of “what kind of request is this”, task type, complexity, domain, language, structure. This is exactly what routing needs.&lt;&#x2F;li&gt;
&lt;li&gt;Final layers are for collapsing toward next-token prediction. The representation becomes increasingly specialized for predicting a specific output token, losing the broad task-level signal.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is an interesting one. The loss function for decoder-only LLMs is &lt;code&gt;logits = hidden_state @ W_unembed → softmax(logits) vs true next token&lt;&#x2F;code&gt;. So the final hidden state must produce useful logits when multiplied by the unembedding matrix W_unembed. This means the final layer’s hidden states are optimized to live in the row-space of W_unembed, they need to produce strong dot-products with specific vocabulary vectors. Here’s the key, W_unembed has a small number of dominant singular directions (common tokens like “the”, “is”, “\n”, punctuation dominate the output distribution). The final-layer representations get pulled toward these dominant directions because:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Most training examples have high-probability next tokens that align with these common directions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1907.12009&quot;&gt;Gradient descent moves the hidden states toward regions where they produce correct logit patterns&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Over billions of training steps, this creates a systematic bias, the hidden states cluster along the principal components of W_unembed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;two semantically very different prompts (“write Python code to sort a list” vs “translate this poem to French”) end up with final-layer hidden states that have &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aclanthology.org&#x2F;D19-1006.pdf&quot;&gt;cosine similarity ~0.7-0.9&lt;&#x2F;a&gt;, because both are being pulled toward the same dominant W_unembed directions. The “what kind of task is this” information gets overwritten by “what distribution of next tokens is likely here.”&lt;&#x2F;p&gt;
&lt;p&gt;The technical name for this is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aclanthology.org&#x2F;2024.eacl-long.3.pdf&quot;&gt;anisotropy problem&lt;&#x2F;a&gt;. final-layer representations of decoder LMs cluster into a narrow cone aligned with the dominant vocabulary embedding directions. The last few layers increasingly project toward dominant eigenvectors of the unembedding matrix, see the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.lesswrong.com&#x2F;posts&#x2F;AcKRB8wDpdaN6v6ru&#x2F;interpreting-gpt-the-logit-lens&quot;&gt;logit lens effect&lt;&#x2F;a&gt;. This means cosine similarity between ANY two final-layer representations is high regardless of input content. Two completely different prompts will have high cosine similarity at the final layer because both representations are being pulled toward the unembedding matrix’s principal components. A linear probe on these representations loses discriminative power because the geometric spread has collapsed.&lt;&#x2F;p&gt;
&lt;p&gt;Middle layers aren’t directly optimized to produce logit distributions. They serve as intermediate computational stages. Their representations are shaped by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The need to pass useful information upward to later layers&lt;&#x2F;li&gt;
&lt;li&gt;The residual stream accumulating information from attention + FFN blocks&lt;&#x2F;li&gt;
&lt;li&gt;NO direct pressure to align with W_unembed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So middle-layer hidden states remain more isotropic, they spread across the full d-dimensional space, preserving geometric separability. A linear probe can easily find hyperplanes that separate “coding task” from “creative writing” from “factual Q&amp;amp;A” because these categories occupy genuinely different regions.&lt;&#x2F;p&gt;
&lt;p&gt;The narrow cone isn’t the entire d=2048 space collapsing, it’s 1-3 dimensions with enormous norms pulling everything in their direction. so we can capture variance in the non-rogue dimensions using the dispersion feature (max-pool − mean-pool across token positions at layers) captures how much the tokens disagree with each other at the semantic level, a measure of input heterogeneity&#x2F;complexity that’s maximally informative in the layers where tokens have been semantically processed but haven’t yet collapsed toward the prediction bottleneck. This is beautiful insight for anyone building low latency routers (discriminative features required).&lt;&#x2F;p&gt;
&lt;p&gt;The self attention itself causes this anisotropy problem. it appears even in character-level models and non-NLP transformers (vision, audio). Anisotropy is a structural property of self-attention, not just a side-effect of the training objective.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-basics-of-model-serving&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-basics-of-model-serving&quot; aria-label=&quot;Anchor link for: some-basics-of-model-serving&quot;&gt;Some basics of model serving&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;LLM serving has two different phases with very different performance characteristics:
Prompt &#x2F; prefill phase:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;when the model reads the input tokenised prompt all available upfront (tokens are known so attention can be computed for all positions simultaneously) so the model can process them all in parallel using matmuls at full GPU throughput (its takes ms) and get those KV (which are very large so we build KV cache)&lt;&#x2F;li&gt;
&lt;li&gt;Mostly compute-bound (GPU working hard) so highly parallel&lt;&#x2F;li&gt;
&lt;li&gt;Affects time-to-first-token (TTFT)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Decode &#x2F; generation phase:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Generates the response one token at a time (new token depends on all previous tokens and becomes the part of new input) till stopping criteria is met (max length or end of sequence), doing matrix-vector multiplications, one forward pass per token, loading all the model’s weights and KV cache from VRAM.&lt;&#x2F;li&gt;
&lt;li&gt;involves CPU overhead, from assembling the batch to dispatching GPU kernels and reading the results. CUDA graphs eliminate the overhead by recording the full GPU execution sequence once and replaying it for batches with matching shapes&lt;&#x2F;li&gt;
&lt;li&gt;Mostly memory-bandwidth-bound.  The weight matrices are the same size as during the pre-fill, but we are multiplying them by a single vector instead of a matrix. The GPU cores finish this simple work in microseconds and then wait for the next batch of weights to arrive from the memory. The game here is how fast we can stream the model weights from the HBM to the compute units.&lt;&#x2F;li&gt;
&lt;li&gt;Affects time-per-output-token (TPOT)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a 31B parameter model stored in 16-bit floats, the GPU has to load around 62GB of data from memory just to generate one token fragment. The GPU spends most of its time sitting idle, waiting for data to arrive from the memory bus. This is the stutter thing you see in slow LLM responses. The problem is of arithmetic intensity (fancy word to throw around but it’s just how much math happens per byte read from memory ops:byte). Matrix-vector products often have very low arithmetic intensity incase of small batches (chunked often used). The GPU finishes the math almost instantly and then waits for the next batch of weights to arrive from memory. On modern hardware, the GPU is often less than 10% utilized during decode at small batch size!&lt;&#x2F;p&gt;
&lt;p&gt;This distinction matters for production systems. Clearly, the pre-fill throughput scales with the GPU compute, as more flops mean faster pre-fill, and decode throughput scales with memory bandwidth, so the faster memory means the faster decode, and that’s exactly why NVIDIA’s H100s focused on memory bandwidth improvement over the A100s, because it directly speeds up the token generation&lt;&#x2F;p&gt;
&lt;h2 id=&quot;millions-of-tokens-prefilling&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#millions-of-tokens-prefilling&quot; aria-label=&quot;Anchor link for: millions-of-tokens-prefilling&quot;&gt;Millions of tokens prefilling&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;the request is moved from pending to prefilling when the scheduler finds enough token budget and cache space to admit the request at the first place. If the prompt is too long to fit in a single step, the scheduler splits it across multiple forward passes as processing a long prompt in a single step is expensive - because it blocks other requests from generating. Chunked prefill solves this by splitting large prefills across multiple steps. This approach enables interleaving prefill and decode operations, preventing long pauses before the first token appears. So, instead of processing millions of tokens in a single prefill operation, we process chunks of tokens, and the system can begin decoding after the first chunk completes, dramatically reducing time-to-first-token (TTFT) while maintaining full context awareness. We get awesome stall-free scheduling. The schedular can be simple FIFO, or fancier like
&lt;code&gt;PrefillFirstScheduler&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Larger chunks reduce overhead but increase initial latency. Smaller chunks improve responsiveness but add processing overhead. Typical chunking strategy is to have some overlap. Dynamic chunk size helps to optimize for both for both latency and throughput. Works quite well for streaming or low-latency settings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kv-caching&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#kv-caching&quot; aria-label=&quot;Anchor link for: kv-caching&quot;&gt;KV caching&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Oh, this is the base transformer inference optimization. To simply put, during the autoregressive generation, without caching, each token would require recomputing the attention keys and values for all the previous tokens. We just add a simple KV cache that stores the key-value tensors derived from the previous tokens and reuses them for later decoding steps. It is primarily helpful in the decode phase, and it’s basically mandatory for any sort of practical LLM serving. For multi-million token inputs, this cache can consume 80-90% of GPU memory, making cache management critical for latency reduction. Obviously this doesn’t work for the first token, which is why it takes longer to generate.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Cache size (FP16)= 2*2* batch_size* seq_length* num_layers* embeddings_length&lt;&#x2F;code&gt;
pretty much GBs&lt;&#x2F;p&gt;
&lt;p&gt;there are some advanced optimisations like :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;reducing the KV cache memory by grouping multiple queries with same keys and values - Grouped Multi Query Attention&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;prefix-caching&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#prefix-caching&quot; aria-label=&quot;Anchor link for: prefix-caching&quot;&gt;prefix caching&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is KV cache for a shared prompt prefix (cross request KV reuse) and is particularly important for the LLM serving. So, during the Transformers inference, the model computes the key value states for all the prompt tokens and when many requests share the same starting prompt which is like more often than not in the case, the serving engine can use those cached key value pages instead of recomputing them. It’s awesome as it &lt;em&gt;skips repeated prefill, lowers TTFT and input-token cost&lt;&#x2F;em&gt;. vLLM also lists prefix stashing along with continuous batching and chunk prefilling as part of its LLLM serving stamp. vLLM caches the KV cache of existing queries so a new query with the same prefix can reuse it and skip computation for the shared part. this reduces query&#x2F;prefill processing time but does not reduce the time needed to generate new output tokens.&lt;&#x2F;p&gt;
&lt;p&gt;its easy latency reduction on multi-turn conversations. it works the best when the requests share a long stable prefix (should appear first in your prompt structure) like a shared system prompt, a tool or a function schema (often large tool definitions are identical), RAG over a common documents, multi-turn chats, agent frameworks, it is a really good tool to use for overlapping back-to-back requests. but this does not reduce the cost of generating the new output tokens. It mostly reduces the repeated prompt processing work. That’s why from formatting matters. So we should really avoid inserting timestamps, request IDs, user specific metadata, or randomized text before the common prefix, because even the small token difference can break the reuse.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;continuous-batching&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#continuous-batching&quot; aria-label=&quot;Anchor link for: continuous-batching&quot;&gt;Continuous Batching&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Starting batching is just waiting for a batch of requests to arrive and then processing them all together, and then waiting until all of them finish before accepting the new requests. Obviously, this could be problematic because the shorter request would sit idle for the rest of the decoding step to finish. Continuous batching simply inserts the new request into the batch as soon as any request completes. The batch is then re-evaluated at every decode step, so a request that finishes quickly is immediately replaced by a waiting request. Well, we don’t always have uniform inputs, in which case the continuous batching would have matched the static batching, but often, because we have variable lengths, so continuous batching delivers improved throughput because the GPU slots never really sit idle.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;model-pruning-and-compression&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#model-pruning-and-compression&quot; aria-label=&quot;Anchor link for: model-pruning-and-compression&quot;&gt;model pruning and compression&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Among billions of parameters, some are bound to be less important than others. Pruning (or if you wanna sound cool network sparsity) involves removing weakly important parameters from pre-trained models. Modern NNs are overparamatrized, so removeing some parameters shouldn’t harm accuracy. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1803.03635&quot;&gt;Lottery Ticket Hypothesis&lt;&#x2F;a&gt; suggests that a subnetwork exists for every neural networks, which when trained in isolation, reach test accuracy comparable to the original model. Identifying the winning ticket (subnetwork) is crucial, and can be derived by pruning a pre-trained network. Moderate pruning sometimes improves generalisation (we know &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1812.11118&quot;&gt;overparamatrization is bad as it can lead to overfitting&lt;&#x2F;a&gt;) across different domain (after another round of recovery fine tuning). So, we need to be careful with this. Quantization is generally the first compression attempt. Pepole also do quantization-aware or compression-aware training (model learns under the constraints of compression), which is more complex but best in class especially for low latency real-time ML with high accuracy. Also, another concern to note is that pruning often requires fine-tuning on pruned model, which is additional training time.&lt;&#x2F;p&gt;
&lt;p&gt;Another way to compress is using weight clustering. So you can map model weights to a discrete set of pre-computed or learned values. And similar weights are replaced by the shared approximate values. This also reduces the model size. But it’s often noted that it does not necessarily make infants faster because it can actually introduce a look-up overhead. So it’s a good option to keep in mind in case the storage foot print has the main concern.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quantization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#quantization&quot; aria-label=&quot;Anchor link for: quantization&quot;&gt;quantization&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Supposedly, you have some Llama model of 70 billion parameters, and each parameter is a 16-bit floating-point number that is like 140 GB. A single typical A100 has 80 GB of VRAM, so I can’t even load weights on that, let alone run inference on a single GPU. I need multiple such A100s to just serve one model. If you observe closely, 16 bits per parameter is actually quite wasteful. Most weights in a neural network cluster near zero, and the full dynamic range of FP16 is almost entirely unused. If you measure the actual distribution of weights in the Llama model, most of them (I think more than 90% of them) will fall between -0.1 and 0.1. Basically, we are burning 16 bits to represent values that could be stored in simple 4. That’s where quantization comes into play. It replaces these high precision numbers with low precision ones. And the whole trade-off is of accuracy, because every bit you remove destroys some information, so the question is how much accuracy we can lose. It’s a trade-off, right? A well-quantized INT4 model retains almost 95 to 99% of the original quality on most benchmarks, but a naive quantization to INT4 can destroy the model entirely, and the difference is of techniques.&lt;&#x2F;p&gt;
&lt;p&gt;So, quantization means storing and&#x2F;or computing model weights (model.safetensors) and activations in lower precision to get faster memory reads. Lot of nasty stuff here like RTN, AWQ, FP8, GGUF, bits and bytes, etc.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;FP16&#x2F;BF16 is baseline production inference, but FP8 reduces model memory by about 2x and improving throughput up to about 1.6x with minimal accuracy impact. You can take entire tensor (that is the standard method), or you can do this per channel or per group, whatever. This is what RTN (Round to Nearest) approach is. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2210.17323&quot;&gt;Below 4-bit, accuracy drops if we dont do post training quantization&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2306.00978&quot;&gt;AWQ (Activation-aware Weight Quantization)&lt;&#x2F;a&gt; preserves important weights at higher precision. The key observation is that not all weights contribute equally to output quality. Protect the weights&#x2F;channels that matter most for model outputs. Quantize the rest aggressively. AWQ identifies salient channels using activation statistics and protects those channels through scaling, while still using hardware-friendly low-bit weight quantization. The AWQ paper states that protecting only about 1% of salient weights&#x2F;channels can substantially reduce quantization error. AWQ does not literally keep random important individual weights in high precision at runtime in a naive mixed-precision way. That would be hardware-inefficient. AWQ uses activation-aware scaling so the post-training quantized representation preserves important channels better.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All about the glories of quantization, but there are some clear failure modes as well. First of all quantization can introduce range mismatch problems. So if the quantized weights or the activations do not match the ranges of the original model, the accuracy often deviates. So most probably we need to check whether the quantized weights and activations remain within the expected ranges compared with the original model. Second quantization can create a model compression artifact that are not captured by ordinary aggregate metrics. So, actually we should &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2310.04621&quot;&gt;avoid compressing at the final output layer&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By the way, just a side note, not everything in a model tolerates quantization equally. There is a sensitivity hierarchy:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Weights are the most robust of them because they change slowly during the training and follow a roughly Gaussian distribution centered near zero, so they quantize pretty well. I mean that an int8 weight with per-channel scales produces nearly lossless results. Int4 requires a more sophisticated method, but it works.&lt;&#x2F;li&gt;
&lt;li&gt;Activations are moderately sensitive. They are intermediate values flowing through the network during the inference, so they have a bit wider dynamic range than the weights and contain some outliers as well. A single attention head might produce activation values that are 100x or something like larger than the mean. These outliers are critical for the model quality, actually, so quantizing them naively destroys a lot of information. In case of that, we keep the outlier channels in high precision to save them.&lt;&#x2F;li&gt;
&lt;li&gt;KV cache is very sensitive. It stores the attention states for all the previous tokens, so at long context length the KV cache dominates the memory. Quantizing the KV cache saves massive memory, but any error compounds across all the future attention computations, so the quality impact scales with sequential length.&lt;&#x2F;li&gt;
&lt;li&gt;Attention logits are the most sensitive. The softmax and attention are highly sensitive to small changes in their input. A quantization error of even 0.01 in a pre-softmax logit can shift the attention distribution meaningfully. Most quantization schemes keep attention computation in high precision even when everything else is quantized.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;btw, you can also quantize the kbcache so you can store the values in int8 or int4 format instead of fp16 and reduce the memory footprint by 2 to 4 times with minimal accuracy impact.&lt;&#x2F;p&gt;
&lt;p&gt;Quantization actually hurts when you are compute bound, which is kinda counterintutive. its just a trade, you reduce memory bandwidth requirements (smaller weights = fewer bytes to load from HBM) but add dequantization compute (converting INT8 back to fp16&#x2F;fp32 for the actual matmul). When you’re memory-bandwidth-bound (like decode-phase serving), this trade is massively profitable, you load half the bytes and the extra dequant math is trivially hidden by the memory latency. But when you’re already compute-bound (like 4k-token prefill), the GPU’s arithmetic units are already saturated. Adding dequant ops just piles more work onto an already-full pipeline. The diagnostic is simple, if batching doesn’t meaningfully reduce per-request latency, you’re compute-bound, and quantization will hurt. the GPU is maxing out its tensor cores, not waiting on memory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speculative-decoding&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#speculative-decoding&quot; aria-label=&quot;Anchor link for: speculative-decoding&quot;&gt;speculative decoding&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Gemma 4 pulled this off nicely, and achieved a 3x speedup in inference with zero loss in quality.&lt;&#x2F;p&gt;
&lt;p&gt;Autoregressive decoding is slow because the model usually generates one token at a time at inference. Each time the model produces a token, it reads that token back as input and runs another full forward pass through all its layers to produce the next one. Each output depends on everything before it, so you cannot skip ahead or parallelize generation. You are always waiting for token N before you can start token N+1. Basically, sequential token generation with a hard dependency chain. Without any optimization, generating those token n requires recomputing attention for all the N-1 previous tokens. That would be O(N^2) per generated token or O(N^3) total for the sequence length of N. KVCache solves this exactly where after computing K and V for each token we simply store them and when generating the token N+1 we just need to compute KVCache solves this exactly, where after computing K and V for each token, we simply store them and when generating the token N plus 1, we just need to compute the query for the new token and look up the cached keys and values from all the previous tokens. KV Cache solves this exactly where after computing K and V for each token we simply store them and when generating the token N+1 we just need to compute the Q for the new token and look up the cached keys and values from all the previous tokens. This reduces per-token cost from O(N) to O(1) for KV Cache computation. Though the attention score calculation is still O(N) because we will still need to attend to all the previous positions, just that we avoid redundant matmuls on the input now.&lt;&#x2F;p&gt;
&lt;p&gt;Note, generating a token from scratch is expensive, but checking whether a given token is correct is cheap. Speculative uses a cheaper smaller (each pass is cheap because the model is tiny) draft model to guess multiple future tokens, then asks the main model to verify them in parallel (one forward pass over all draft tokens simultaneously and produces a probability distribution over what each token should have been like profile - parallel, compute bound, efficient).&lt;&#x2F;p&gt;
&lt;p&gt;Draft model proposes:
“the answer is probably A B C D”&lt;&#x2F;p&gt;
&lt;p&gt;Target model verifies in one larger pass:
A accepted
B accepted
C accepted
D rejected&lt;&#x2F;p&gt;
&lt;p&gt;Then continue from the accepted prefix. If several draft tokens are accepted, we saved multiple expensive target-model decode steps. The target model remains the authority to either reject or accept the token. The draft model only proposes. If the draft is wrong at position i, tokens after position i are discarded and inference continues normally from there. If the verification algorithm i.e rejection sampling is implemented correctly, the final output distribution can be preserved, so quality should not degrade. It’s not really an approximation. There is a mathematical equivalence at play here. Obviously, the speedup from speculative decoding depends on the acceptance rate, so if its structured text like code, repetetive patterns, factual calls, drafter gets most tokens right and the acceptance rate is high. It works less well if you are creative. For most use cases, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2211.17192&quot;&gt;speculative decoding is better than standard inference&lt;&#x2F;a&gt;. so vLLM, SGLang, etc all support it.&lt;&#x2F;p&gt;
&lt;p&gt;The verification can be parallelized as you already have the draft tokens and you can feed the entire sequence into the target model at once as a single forward pass, but generation cannot as we do not have the next token yet. To produce token N+1, the model must condition on token N. There is no way around this. This asymmetry is precisely what speculative decoding exploits. Take it as pipeline parallelism in CPUs!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2503.01840&quot;&gt;EAGLE-3&lt;&#x2F;a&gt; is a new speculative decoding method. It moves away from earlier feature-prediction constraints, uses direct token prediction, by training a small auto-regressive head on top of the target model’s hidden state. It operates on the target model’s own representation and not on a separate model. It achieves a higher acceptance rate with minimal extra memory. The paper reports speedups up to 6.5x in its experiments and a 1.38x throughput improvement in SGLang at batch size 64. speculative decoding mostly improves decode latency, not initial prompt prefill. So if your requests have enormous prompts and generate only 10 tokens, prefix caching and chunked prefill may matter more.&lt;&#x2F;p&gt;
&lt;p&gt;a thing to note here is that speculative decoding is mathematically exact. The output distribution is identical to the target model’s distribution (not really an approximation). The verification step is there to ensure that every accepted token has exactly the same probability that the target model would have assigned.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;python-overhead&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#python-overhead&quot; aria-label=&quot;Anchor link for: python-overhead&quot;&gt;Python overhead&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;At small model size, naive Python code overhead is large&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;cuda graphs (xFormers has a great example particularly in accelerating FlashAttention and linear layers)&lt;&#x2F;li&gt;
&lt;li&gt;tensorrt-llm (tracing the inference + pattern matching)&lt;&#x2F;li&gt;
&lt;li&gt;custom kernels (fusion to reduce memory bandwidth)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-drives-these-metrics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-drives-these-metrics&quot; aria-label=&quot;Anchor link for: what-drives-these-metrics&quot;&gt;What drives these metrics?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Fixed Flops &#x2F; Memory Bandwidth ratio = Minimal batch size B* to avoid wasting flops&lt;&#x2F;li&gt;
&lt;li&gt;Limited on device memory = Not trivial to reach this batch-size B*&lt;&#x2F;li&gt;
&lt;li&gt;Python code overhead = In vLLM &#x2F; TGI - not FasterTransformer but harder to deploy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Do the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kipp.ly&#x2F;p&#x2F;transformer-inference-arithmetic&quot;&gt;transformer inference arithmetic&lt;&#x2F;a&gt; for your needs. Open source deployment solutions are very usable, but not very optimized for small models&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-about-routing-models&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-about-routing-models&quot; aria-label=&quot;Anchor link for: what-about-routing-models&quot;&gt;What about routing models&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;the router models lives entirely in prefill regime: we tokenize the prompt, run one forward pass through the encoder, extract hidden states, done. No KV cache, no autoregressive loop, no speculative decoding. Just one big parallel matmul party. so optimization game is different from generative models.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>some insights on HNSW</title>
          <pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/some-insights-on-hnsw/</link>
          <guid>https://harsh-ps-2003.github.io/writes/some-insights-on-hnsw/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/some-insights-on-hnsw/">&lt;p&gt;Suppose your RAG pipeline has embedded millions of docs. A user asks a question, and the system converts that query into a high-dimensional vector and needs to find the closest matches. The brute-force approach would be an exact kNN, just computes the distance between the query vector and every vector in the database. That’s O(N·d). With 10 million vectors at 1,536 dimensions, you’re looking at ~15 billion floating-point operations per query. Not viable at production latency.&lt;&#x2F;p&gt;
&lt;p&gt;Now this exactness of kNN is enemy of speed for us in high-dim vector searches.  Exact nearest neighbour search typically requires checking every point, which is O(n). ANN (approximate) methods trade a tiny fraction of precision&#x2F;accuracy (recall) for a massive boost in performance by avoiding exhaustive comparisons. Instead of demanding the single mathematically perfect nearest match, ANN focuses on rapidly finding the best candidates in the right neighbourhood. This in practice is often sub-linear behaviour (like log) and you can often tune ANN to achieve 95–99% recall while cutting latency from seconds to milliseconds.&lt;&#x2F;p&gt;
&lt;p&gt;HNSW has become the dominant ANN approach because it handles this trade-off really well. It combines two ideas: a Navigable Small World (NSW) graph, where vectors are connected to their neighbors like a social network, and a probabilistic skip list that stacks these graphs into multiple layers of varying density.&lt;&#x2F;p&gt;
&lt;p&gt;Small world just means that in the network, we can get from one place to another in surprisingly few hops if the network has the right mix of local connections and a few long-range shortcuts.&lt;&#x2F;p&gt;
&lt;p&gt;In simpler terms, HNSW builds a network of shortcuts so you can reach the right area quickly, then do a small local search to find the best match. Most vectors exist only in the bottom layer. A smaller fraction appear one layer up. An even smaller fraction appear above that. This creates the hierarchy. When we want to search, we start from top layer (tiny so quick to explore), then from our current node, we jump to the neighbour that looks closest to the query. We keep doing this until none of the neighbours is closer. We take the best node we found as our new starting point on the next layer down. Go deeper, till we are exploring a limited set of nearby candidates to produce the final nearest neighbours.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;other-players-in-ann&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-players-in-ann&quot; aria-label=&quot;Anchor link for: other-players-in-ann&quot;&gt;Other players in ANN&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;HNSW is the most used one, but different constraints call for different approaches.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;KD-Trees (k-dimensional tree) is used to organize data points in a multi-dimensional space, where the core structure is a decision tree for each space. At each level, the decision splits into halves and one dimension is chosen at a time. Queries traverse each tree to find candidate neighbors. It works well for low-dimensional data, but search performance can degrade as dimensionality increases. HNSW, in contrast, can maintain search speed even when the data structure gets complex.&lt;&#x2F;li&gt;
&lt;li&gt;LSH (Locality-Sensitive Hashing) organizes data using random hash functions to bucket similar vectors so that searches can find the right ones quickly. By hashing the query, searches can only look up vectors in a corresponding bucket. It tends to work best in cases where the data is extremely high-dimensional, or vectors are sparse. LSH is memory efficient, but recall can suffer as a result, which means HNSW is often a better approach for teams that need high accuracy, even if HNSW tends to require greater memory usage.&lt;&#x2F;li&gt;
&lt;li&gt;IVF (Inverted File Index) partitions the space into clusters. A search first picks the most promising clusters, then searches within those buckets. It’s often chosen when we want lower memory usage than HNSW or more explicit control over partitioning.&lt;&#x2F;li&gt;
&lt;li&gt;PQ (Product Quantization) compresses vectors into compact codes. This enables far larger collections to fit into memory, but with some loss of precision. It’s a common choice when memory is the bottleneck and we’re working at very large scale.&lt;&#x2F;li&gt;
&lt;li&gt;DiskANN keeps much of the structure on SSD rather than RAM, optimizing the layout to reduce random reads. It’s designed for datasets that simply won’t fit in memory, while still aiming for strong performance.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;HNSW is at its most effective when we use it for large datasets, especially ones that include over one million documents and in situations when search performance and scalability are higher priorities than perfect accuracy. Due to its graph-based structure, requires much more memory than other ANN methods. With larger amounts of connections per node, HNSW can get even more memory-intensive. We need to hyperparamater tune properly.&lt;&#x2F;p&gt;
&lt;p&gt;HNSW is best for in-memory, monolithic indexing, so it tends to suffer in distributed environments. HNSW is shardable, but sharding creates additional complexity and requires more memory to manage the various pieces.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quantization-paradox&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#quantization-paradox&quot; aria-label=&quot;Anchor link for: quantization-paradox&quot;&gt;Quantization paradox&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;HNSW latency is dominated by distance computations. If you use Scalar Quantization (SQ) or Product Quantization (PQ), you can compute distances 4x–10x faster using SIMD (AVX-512) instructions. Because distances are cheaper, you can set a much higher &lt;code&gt;ef_search&lt;&#x2F;code&gt; (the number of candidates tracked during search) while staying within your latency budget. In many benchmarks (like Weaviate’s), searching a larger neighborhood with lower-precision vectors yields higher recall than searching a tiny neighborhood with high-precision vectors. So, don’t just tune ef_search on raw vectors. Quantize first, then spend your saved latency on a wider search.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tackling-the-silent-failure&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tackling-the-silent-failure&quot; aria-label=&quot;Anchor link for: tackling-the-silent-failure&quot;&gt;Tackling the silent failure&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;HNSW recall isn’t a constant for obvious reasons. As your corpus grows from 10k to 10M vectors, the Small World connectivity becomes harder to maintain. A configuration that gives 99% recall at 100k vectors might drop to 80% at 10M vectors without changing a single line of code. In high-dimensional space, certain vectors naturally become “hubs” that attract a disproportionate number of incoming edges. These hubs can act as “gravity wells,” pulling search queries away from the true nearest neighbors. So clearly, we need to play with hyperparams! Tip - Before scaling your production cluster, build a Shadow Index with 10% of your production traffic being mirrored to a brute-force (flat) index. Compare the IDs. If your Truth starts drifting, it’s time to bump M or ef_construction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-disconnected-graph-filter-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-disconnected-graph-filter-problem&quot; aria-label=&quot;Anchor link for: the-disconnected-graph-filter-problem&quot;&gt;THe Disconnected Graph Filter Problem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One of the biggest practical gotchas in RAG is filtered search (e.g., “Find docs about X, but only for user_id=123”).&lt;&#x2F;p&gt;
&lt;p&gt;If your filter is very restrictive (e.g., only 0.1% of docs match), HNSW breaks. The search enters the graph, but most neighbors are “invalid” due to the filter. The search gets stuck in a “local island” of filtered-out nodes and can’t find the path to the valid ones.
The fic is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2403.04871&quot;&gt;ACORN algorithm&lt;&#x2F;a&gt; (recently adopted by Qdrant and Lucene). It modifies HNSW to perform 2-hop expansions. If your neighbors don’t match the filter, you check their neighbors. This keeps the graph navigable even when 99% of nodes are invisible to the current query.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-diversity-heuristic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-diversity-heuristic&quot; aria-label=&quot;Anchor link for: the-diversity-heuristic&quot;&gt;The Diversity Heuristic&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;During insertion, HNSW doesn’t just pick the closest neighbors. It uses a heuristic: “Only add a neighbor if it is closer to me than it is to any neighbor I’ve already picked.” This forces the algorithm to pick neighbors in different “directions” (angular diversity). Without this, if you had a cluster of 100 very similar vectors, HNSW would connect only to that cluster and become “blind” to the rest of the world. It’s the algorithmic version of “don’t just talk to people who agree with you.”&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware-aware-indexing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hardware-aware-indexing&quot; aria-label=&quot;Anchor link for: hardware-aware-indexing&quot;&gt;Hardware Aware Indexing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Indexing 10M vectors on a standard CPU can take days. However, using libraries like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nvidia.com&#x2F;en-us&#x2F;on-demand&#x2F;session&#x2F;gtc25-s71675&#x2F;&quot;&gt;NVIDIA cuVS (GPU-accelerated HNSW)&lt;&#x2F;a&gt;, you can drop index construction time from 28 days to 1.4 days. If your data is highly dynamic (lots of deletions&#x2F;updates), HNSW fragmentation will eventually ruin your recall. Instead of trying to fix the graph, it is often more practical to just rebuild the index from scratch every week using a GPU-accelerated runner.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>how package managers use PubGrub for Dependency Resolution</title>
          <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/pubgrub-for-dependency-resolution/</link>
          <guid>https://harsh-ps-2003.github.io/writes/pubgrub-for-dependency-resolution/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/pubgrub-for-dependency-resolution/">&lt;p&gt;There are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nesbitt.io&#x2F;2026&#x2F;02&#x2F;06&#x2F;dependency-resolution-methods.html&quot;&gt;all sorts of dependency resolution methods&lt;&#x2F;a&gt; used by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ecosyste-ms&#x2F;package-manager-resolvers&quot;&gt;various package managers&lt;&#x2F;a&gt;, but I am specifically writing on PubGrub as it’s used in uv package manager which I used to contribute to get some insights on how pro peps write Rust. In short, PubGrub is popular as :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tracks incompatibilities and produces human-readable conflict explanations&lt;&#x2F;li&gt;
&lt;li&gt;Uses CDCL (conflict-driven clause learning) like modern SAT solvers, pruning search space efficiently&lt;&#x2F;li&gt;
&lt;li&gt;Has intellignnt backtracking to the right decision point instead of naive retries&lt;&#x2F;li&gt;
&lt;li&gt;And, a lot of good quality implementations are readily available&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can go through it’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pubgrub-rs-guide.pages.dev&#x2F;internals&#x2F;intro&quot;&gt;internals&lt;&#x2F;a&gt; and better, listen to the a&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;Fifni75xYeQ?si=DDQRYePmNWhZgXgu&quot;&gt;wesome lightening talk by its creator at DartConf&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The thing that nudged me to write this is something about concurreny. The PubGrub algorithm is a tight synchronous loop with complex mutable state that doesn’t fit naturally into async&#x2F;await (so cant be async as its sequential).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;uv-being-clever&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#uv-being-clever&quot; aria-label=&quot;Anchor link for: uv-being-clever&quot;&gt;uv being clever&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;What’s clever is that uv completely decouples the synchronous solver from parallel I&#x2F;O using a two-thread architecture with channels:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the uv-resolver (the dedicated synchronous thread) - Runs PubGrub loop normally, when it needs metadata, sends request via mpsc::channel(300) and calls wait_blocking() which blocks only the solver thread (not the entire tokio runtime). THis is sync so no async&#x2F;await to reason about here.&lt;&#x2F;li&gt;
&lt;li&gt;Fetcher (async tokio pool) - Receives requests, fires hundreds of concurrent HTTP requests to PyPI, writes results to shared Arc&lt;DashMap&gt; cache (zero-copy deserialization, readers dont wait on mutexes)
They also do some perf optimizations :&lt;&#x2F;li&gt;
&lt;li&gt;Prefetching - After 5 failed versions of a package, speculatively fetches the next 50 versions in parallel before the solver ever needs them&lt;&#x2F;li&gt;
&lt;li&gt;Conflict-priority heuristic - After 5 conflicts between packages A and B, promotes B’s priority above A’s and manually backtracks to decide B first&lt;&#x2F;li&gt;
&lt;li&gt;Forking resolver -Splits resolution on environment markers (e.g., python_version &amp;gt;= “3.11”), producing one universal lockfile for all platforms&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;SOoo, PubGrub stays simple and synchronous, but the solver can queue up to 300 requests before blocking, and those requests are served concurrently. Te network I&#x2F;O get fully concurrent, biggest bottleneck (metadata fetching) gets parallelized without touching the solver logic.
See the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astral-sh&#x2F;uv&#x2F;pull&#x2F;3627&quot;&gt;PR&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;others&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#others&quot; aria-label=&quot;Anchor link for: others&quot;&gt;Others?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Dart’s original implementation was obviously sequential. I dont know why Poetry and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=25294410&quot;&gt;pip (Python) also is sync&lt;&#x2F;a&gt; featching one package at a time. Swift does lazy fetching (doesn’t fetch metadata until after resolution decides a version, but still sequential, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forums.swift.org&#x2F;t&#x2F;why-is-fetching-dependencies-with-swiftpm-so-slow&#x2F;67191&quot;&gt;users report slowness&lt;&#x2F;a&gt;). Cargo (rust) is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo&#x2F;issues&#x2F;15934&quot;&gt;blocking during resolution&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;yarn and npm (the javascript world) is an interesting piece over here as they use async&#x2F;await throughout the entire solver code, whereas uv keeps PubGrub fully synchronous and only parallelizes I&#x2F;O via a separate thread. JavaScript is single-threaded with async by default. There’s no way to write blocking code that doesn’t block the entire event loop. So they had to make everything async. It uses Single-threaded event loop + libuv thread pool (heavy lifting happens in libuv’s C++ threads). await fetchPackage(pkg) returns a Promise immediately; event loop switches to other tasks. Event loop never blocks, promises resolve later, JavaScript keeps running other code. As it uses single heap, references are naturally shared so no cross-thread synchronization needed.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>the longer you chat, the worse your agent&#x27;s response</title>
          <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/the-longer-you-chat-the-worse-your-agents-response/</link>
          <guid>https://harsh-ps-2003.github.io/writes/the-longer-you-chat-the-worse-your-agents-response/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/the-longer-you-chat-the-worse-your-agents-response/">&lt;h2 id=&quot;just-for-the-sake-of-basics-whats-an-agent&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#just-for-the-sake-of-basics-whats-an-agent&quot; aria-label=&quot;Anchor link for: just-for-the-sake-of-basics-whats-an-agent&quot;&gt;Just for the sake of basics, whats an agent?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;LLM is just autocomplete. No reading files, no running a query, forget about opening a browser, verifying a claim. The model will have outdated information and it will confidently say that slop. An agent is different. An agent is a system where a model operates in a loop, observing state, selecting actions, and incorporating results until a goal is met or a stopping condition is reached. An agent has three components: a model that decides, tools that execute, and a loop that connects them. The model reads the current state, system prompt, conversation history, tool results, and outputs either a tool call or a final answer. If it outputs a tool call, the tool executes, the result is appended to the state, and the model is called again. If it outputs an answer, the loop terminates. If neither, the loop continues until a stopping condition is reached. Every model has a finite context window, the maximum number of tokens for one inference call, counting both input and output. In a long agentic session with many tool calls, the conversation history can easily exhaust this limit.&lt;&#x2F;p&gt;
&lt;p&gt;On a more formal note, a Markov Decision Process is a tuple ⟨S, A, P, R, γ⟩ where the system observes state (the context window (system prompt + message history + tool results)), selects an action according to a policy (respond to user, call a tool, request information, terminate), transitions to a new state (deterministic for tool execution, stochastic for LLM reasoning), and receives a reward signal (task completion (implicit) or user feedback (explicit)). The last one being discount, that is to prefer prefer shorter paths, fewer API calls, lower cost, less error accumulation. Basically, at each step, pick the action that maximizes expected future reward from the current state. The model’s system prompt, its training, and any examples in the prompt collectively approximate this strategy. The Markov property states that the next action depends only on the current state, not on how the agent got there. For an LLM agent, the current state is the context window, the system prompt, the conversation history, and every tool result so far. What is in that window is all the model knows. What is not in it does not exist to the agent. This is why memory and context management matter at scale.&lt;&#x2F;p&gt;
&lt;p&gt;At the end, there are only three levers, better state (memory, tool results), better actions (more capable tools), or a better policy (prompting, fine-tuning, reasoning strategies).&lt;&#x2F;p&gt;
&lt;p&gt;By now we have established that AI agents are nothing but loops. The agent loop sends HTTP requests to the Responses API, building an ever-growing JSON prompt from system instructions, tool definitions, sandbox permissions, and conversation history. Now every agent loop, regardless of framework, model, or complexity, requires exactly three components. a protocol its gonna follow, a registry, and a loop with a termination condition.&lt;&#x2F;p&gt;
&lt;p&gt;The most common protocol would be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2210.03629&quot;&gt;ReAct&lt;&#x2F;a&gt; as it combined Chain of Thought with Action (think then act and then reason about the response you got) to avoid assumtptions that agent makes without concrete information. Feels like simple RL, but without discrete action space, if you really have open action space, will we ever converge? But LLMs are so good, there is not an issue of cold start (it has info about the world better than humans). So, only Act would be to make an observation and then sample an action space based on the observation (and the trajectory so far). ReAct just expands the action space with natural language (strong priors required, thus good models are needed). In CoT, even if the reasoning is wrong, it can still sometimes give right answer, but with ReAct, we need evidence. So CoT helps when there is domain knowledge, ReAct is better overall framework. Another common addition is of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2303.17651&quot;&gt;SELF-REFINE&lt;&#x2F;a&gt; which suggests to generate output however required, wheather its direct prompting, CoT, self consistency, ReAct, whatever, but once you arrive at solution, just reflect and introspect. For an example, suppose you have a code editing agent. Even if the task was to generate some code, after generating output we can agent can introspect on complexity, to refine the output even more. And the feedback can be multi-dimensional as well, like coherence, relevance, etc, and the iteration goes on until the output is solid enough. Feedback here is hard actually, because model needs to understand it. Another extension was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2303.11366&quot;&gt;Reflexion&lt;&#x2F;a&gt; where the self introspection happens using tools involved as well which is more practical and recovery from failure was better.  But a thing to keep in mind is that , &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2201.11903&quot;&gt;CoT prompting improves performance on many reasoning tasks, but it should not be treated as a correctness guarantee&lt;&#x2F;a&gt;. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2305.04388&quot;&gt;Models don’t always say what they think&lt;&#x2F;a&gt;, so prefer &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2301.13379&quot;&gt;Faithful CoT&lt;&#x2F;a&gt; which tries to translate reasoning into symbolic or executable steps that can be checked by a deterministic solver, which is much closer to production correctness than simply asking the model to “think step by step.”&lt;&#x2F;p&gt;
&lt;p&gt;So,
Precise agent = controller + state ledger + tools + retrieval + verifier + compactor
where,
controller: decides the next action
state ledger: stores objective, constraints, decisions, assumptions, artifacts
tools: interact with the world
retrieval: selects external evidence
verifier: checks claims&#x2F;actions against tests or evidence
compactor: updates state without losing invariants&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-modern-way&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-modern-way&quot; aria-label=&quot;Anchor link for: the-modern-way&quot;&gt;the modern way&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;originally, model had only one channel for text tokens. so reasoning was hacky with prompts like “think step by step” and by stuffing CoT text into same stream of tokens as final answer (or you manually filter it). The thought is mixed with normal tokens, the final answer and internal work is smudged together. &lt;code&gt;prompt + visible text (includes reasoning and answer) → next prompt&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;these days for reasoning-focused models and APIs we have a native reasoning channel. The model produces:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;User-visible content: what the end user sees.&lt;&#x2F;li&gt;
&lt;li&gt;Reasoning content: a structured trace &#x2F; scratchpad, possibly large, not meant for the user. This reasoning content - has its own token budget, can be passed back into the next call so the model remembers how it was thinking, without dumping all that into user-visible tokens, may be encrypted &#x2F; hidden across providers in production
&lt;code&gt;prompt → {answer_channel, reasoning_channel}&lt;&#x2F;code&gt; and in next turn &lt;code&gt;{new_observation, previous_reasoning_channel} → new {answer, reasoning}&lt;&#x2F;code&gt; to new &lt;code&gt;{answer, reasoning}&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-this-system-design&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-this-system-design&quot; aria-label=&quot;Anchor link for: why-this-system-design&quot;&gt;Why this system design?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;just wait until your 2-hour agent run fails at step 99 of 100, and you will get the answer!&lt;&#x2F;p&gt;
&lt;p&gt;When we are building short agents, a simple retry loop is often enough. Each agent call is isolated, cheap, and stateless. Fail, retry, done. But retrying a long-running agent spanning hours is expensive in API costs, tool calls, and wall clock time, and retries can also have side effects involving UX. Some failures that a long-running agent might hit in production are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Context window overflow (this is what I am write about)&lt;&#x2F;li&gt;
&lt;li&gt;trust boundary collapse (tool outputs can contain destructive things)&lt;&#x2F;li&gt;
&lt;li&gt;LLM provider rate limiting (really common)&lt;&#x2F;li&gt;
&lt;li&gt;Network timeouts for downstream calls&lt;&#x2F;li&gt;
&lt;li&gt;Pod eviction and rotation due to OOM that can happen anytime&lt;&#x2F;li&gt;
&lt;li&gt;Human-in-the-loop pauses for god knows how many hours (worse, this dont even fire alerts, just sits silently, no timeout, no escalation, no dead letter queue)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Classic backend engineering problems to solve, where we need checkpoint recovery, idempotency, durable event logs, distributed retries, timeout orchestration and resumable workflows. we need to build robust, fault-tolerant systems by applying hundreds of patterns. System design is for operational challenges, not just fancy multi-agent orchestration. A long-running agent is basically distributed systems engineering wearing an AI hoodie, even nastier as LLM workflows are slower, probabilistic, and dependency-heavy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-context-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-context-problem&quot; aria-label=&quot;Anchor link for: the-context-problem&quot;&gt;The context problem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You must have felt this! in long-running sessions, there is a point where the agent starts drifting. It forgets a constraint you shoved into its throat minutes ago. It calls the same tool again, with the same inputs. A decision from step two gets contradicted at step nine. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2307.03172&quot;&gt;Its a U-shaped performance curve, LLM performs best when the info occurs at beginning (primacy bias) or end (recency bias) of input context, and worst when the info is located in middle.&lt;&#x2F;a&gt;. Needle-in-a-haystack is too easy because it often rewards lexical matching. Real agents need semantic retrieval, contradiction handling, state tracking, and reasoning over noisy histories. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;engineering&#x2F;april-23-postmortem&quot;&gt;Anthropic reported a Claude Code issue where older reasoning blocks were accidentally cleared on every turn&lt;&#x2F;a&gt;. Users saw forgetfulness, repetition, odd tool choices, and cache misses. The key lesson was that context-management bugs can look like “the model got dumber,” even when the underlying model did not change.&lt;&#x2F;p&gt;
&lt;p&gt;In RAG as well, the retriever has to be good enough because the top K answers that we get should have the answers in it. But if the context window is large enough, then we could actually just have the entire document in the context itself, and we won’t need a very accurate retriever. We won’t really need fine-tuning as well, because we could include all the tasks and examples and all in the context window. Even if the retriever performance is really good in your RAG, it does not matter because the model, the agent, will not be able to see the retrieved documents in the middle. It does not really matter.&lt;&#x2F;p&gt;
&lt;p&gt;Basically you are burning tokens and getting worse answers. Well, welcome to the world of context collapse. Every frontier lab is trying to push for more context windows (just to give you a sense 128k tokens is around 100 pages of doc and 1M is around 2500 pages). wherever it is, the hard limit, degradation starts long before it is reached. Better the context, better the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2307.02477&quot;&gt;reasoning&lt;&#x2F;a&gt; (that is, infer new assertions from a set of assertions integrating multiple knowledge sources, gettng new conclusions) will work, better the tool and MCP calls, and more, common sense. Being a monkey and just increaing the window wont help much in long term. Yet, every announcement leads with the context window. 1M tokens. 2M tokens and entire codebases in one prompt. The implied message is always the same, if the model can read more, it will reason better, which is simply misleading. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2404.06654&quot;&gt;Models claiming long context lengths can still degrade substantially as context grows, especially on multi-hop, aggregation, and variable-tracking tasks rather than simple needle retrieval&lt;&#x2F;a&gt;. The problem is not that context windows are short. The problem is that context is a bad substitute for state. A 1M-token context window can contain the answer and still fail if the answer is buried, contradicted, stale, or surrounded by irrelevant tool output. Long context gives the model more material to condition on; it does not guarantee retrieval, prioritization, consistency, or verification. For high-precision agents, the central engineering problem is not “how do we fit more text?” but “how do we maintain a correct working set?”&lt;&#x2F;p&gt;
&lt;p&gt;Chatgpt’s memory feature gives persistent context across separate conversations. There are two distinct components working together. The first one is chat search, which lets the model retrieve relevant snippets from the past conversations using RAG. There is also memory summary thats given to models but it compresses away details the agent may need later. These burn token really fast as well as add noise.&lt;&#x2F;p&gt;
&lt;p&gt;A critical architectural fact is that every API request is completely stateless. The server holds no session generally. When you’re chatting on chatgpt, the application re-sends the entire conversation history with each new turn (server-side threads, memory, prompt caches, summaries, or tool state). Turn 2 ships Turn 1 + your new message. Turn N ships all N-1 prior turns plus your message. Context grows linearly. The client manages it, not the model. This feels less agentic to me!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2407.16833&quot;&gt;Long context and RAG solve different problems&lt;&#x2F;a&gt;. Long context increases the amount of text the model can inspect in one call. RAG changes the working set by selecting what should be inspected. When the whole corpus is small, relevant, and affordable to pass in, long context can beat retrieval. When the corpus is large, dynamic, private, or noisy, retrieval is still a state-management primitive, not just a token-saving trick.&lt;&#x2F;p&gt;
&lt;p&gt;A context window is closer to RAM than to memory. It is the model’s working set for the next forward pass. It is expensive, temporary, order-sensitive, and easily polluted. Long-term memory, retrieval indexes, files, databases, tool logs, and summaries are different layers of the memory hierarchy. A good agent does not paste everything into RAM. It pages in the right state, keeps pointers to bulky artifacts, compresses old traces, and verifies that compression did not destroy important invariants.&lt;&#x2F;p&gt;
&lt;p&gt;A clean way to reason about this is :&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Agent layer&lt;&#x2F;th&gt;&lt;th&gt;Systems analogy&lt;&#x2F;th&gt;&lt;th&gt;What belongs there&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Active context&lt;&#x2F;td&gt;&lt;td&gt;RAM &#x2F; working set&lt;&#x2F;td&gt;&lt;td&gt;Current request, state ledger, relevant recent turns, selected evidence&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Short-term thread state&lt;&#x2F;td&gt;&lt;td&gt;Process-local state&lt;&#x2F;td&gt;&lt;td&gt;Current plan, active subtasks, unresolved questions&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Long-term memory&lt;&#x2F;td&gt;&lt;td&gt;Database&lt;&#x2F;td&gt;&lt;td&gt;Durable user&#x2F;project facts with provenance&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tool logs&lt;&#x2F;td&gt;&lt;td&gt;Append-only event log&lt;&#x2F;td&gt;&lt;td&gt;Raw observations, commands, search results, actions&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Retrieval index&lt;&#x2F;td&gt;&lt;td&gt;Search engine&lt;&#x2F;td&gt;&lt;td&gt;Documents, code, previous traces, policies&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Compaction summary&lt;&#x2F;td&gt;&lt;td&gt;Checkpoint&lt;&#x2F;td&gt;&lt;td&gt;Lossy but structured continuation state&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;contact-between-agents&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#contact-between-agents&quot; aria-label=&quot;Anchor link for: contact-between-agents&quot;&gt;Contact between agents&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;There has to be structured output between the agents, otherwise systems becomes really fragile.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent A: &amp;quot;I think the issue is probably in auth, maybe retry with the new token.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent B: interprets that differently.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent C: loses the uncertainty.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent D: treats the guess as fact.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&amp;gt; total context collapse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If one agent retrieves evidence, another verifies it, another plans tool calls, and another writes the final answer, they cannot pass around loose natural language and hope the next agent interprets it correctly.&lt;&#x2F;p&gt;
&lt;p&gt;A handoff should specify:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;task_id&lt;&#x2F;li&gt;
&lt;li&gt;agent_role&lt;&#x2F;li&gt;
&lt;li&gt;input assumptions&lt;&#x2F;li&gt;
&lt;li&gt;output decision&lt;&#x2F;li&gt;
&lt;li&gt;evidence used&lt;&#x2F;li&gt;
&lt;li&gt;confidence&lt;&#x2F;li&gt;
&lt;li&gt;uncertainty&lt;&#x2F;li&gt;
&lt;li&gt;open questions&lt;&#x2F;li&gt;
&lt;li&gt;required next action&lt;&#x2F;li&gt;
&lt;li&gt;forbidden next actions&lt;&#x2F;li&gt;
&lt;li&gt;provenance&lt;&#x2F;li&gt;
&lt;li&gt;permissions&lt;&#x2F;li&gt;
&lt;li&gt;expiry &#x2F; validity window&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Structured output gives the system five things :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;First, type safety. The next agent knows whether it received a decision, a draft, a fact, a hypothesis, an error, or a request for clarification.&lt;&#x2F;li&gt;
&lt;li&gt;Second, auditability. You can inspect what each agent believed, what evidence it used, and why it made a decision.&lt;&#x2F;li&gt;
&lt;li&gt;Third, verification. A verifier can check fields like confidence, source, permissions, and validity instead of parsing messy prose.&lt;&#x2F;li&gt;
&lt;li&gt;Fourth, latency control. Structured outputs can be smaller than verbose natural-language traces and easier to route.&lt;&#x2F;li&gt;
&lt;li&gt;Fifth, failure isolation. If one agent produces invalid JSON or misses a required field, the orchestrator can reject the handoff before the mistake propagates.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In serious agentic systems, agents can use language to reason, but they should use schemas to coordinate. Free-form handoffs are where uncertainty, permissions, evidence, and state quietly disappear.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tool-ambiguity-is-context-pollution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tool-ambiguity-is-context-pollution&quot; aria-label=&quot;Anchor link for: tool-ambiguity-is-context-pollution&quot;&gt;Tool ambiguity is context pollution&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;More tools do not always make an agent more capable. If five tools can answer the same question, the agent now has to solve a tool-selection problem before it solves the user’s problem. Overlapping tools create ambiguity, retries, inconsistent behavior, and hidden failure modes. Production agents need a small number of sharp tools with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;clear purpose&lt;&#x2F;li&gt;
&lt;li&gt;clear input schema&lt;&#x2F;li&gt;
&lt;li&gt;clear failure modes&lt;&#x2F;li&gt;
&lt;li&gt;clear permission model&lt;&#x2F;li&gt;
&lt;li&gt;clear output contract&lt;&#x2F;li&gt;
&lt;li&gt;clear verification strategy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The tool-gateway pattern is generally best practice as MCP servers expose power. They may access files, databases, cloud systems, Slack, GitHub, internal metrics, customer records, or production infrastructure. The gateway gives us a central control point.  whenever the agent wants to use an external tool, it has to take approval from policy engine (a simple backend servic generally with rules, context and api contracts), and if its approved, mint a JIT token and then execute the action and log for auditing purpose. Some general gateway checks are :
Gateway checks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is this user allowed to access payments deployment logs?&lt;&#x2F;li&gt;
&lt;li&gt;Is this tenant&#x2F;project correct?&lt;&#x2F;li&gt;
&lt;li&gt;Is this tool allowed for this agent?&lt;&#x2F;li&gt;
&lt;li&gt;Are the arguments safe?&lt;&#x2F;li&gt;
&lt;li&gt;Is the rate limit okay?&lt;&#x2F;li&gt;
&lt;li&gt;Should this call be logged or redacted?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A tool gateway generally handles :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;authentication&lt;&#x2F;li&gt;
&lt;li&gt;authorization&lt;&#x2F;li&gt;
&lt;li&gt;tenant boundaries&lt;&#x2F;li&gt;
&lt;li&gt;tool allowlists&lt;&#x2F;li&gt;
&lt;li&gt;argument validation&lt;&#x2F;li&gt;
&lt;li&gt;secrets management&lt;&#x2F;li&gt;
&lt;li&gt;rate limiting&lt;&#x2F;li&gt;
&lt;li&gt;audit logging&lt;&#x2F;li&gt;
&lt;li&gt;response redaction&lt;&#x2F;li&gt;
&lt;li&gt;human approval for risky actions&lt;&#x2F;li&gt;
&lt;li&gt;tool versioning&lt;&#x2F;li&gt;
&lt;li&gt;tool discovery&lt;&#x2F;li&gt;
&lt;li&gt;policy enforcement&lt;&#x2F;li&gt;
&lt;li&gt;timeout&#x2F;retry&#x2F;circuit breaking&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A simple flow to understand :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;User asks question&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent decides it needs a tool&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent runtime invokes MCP client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MCP client sends a JSON-RPC tool call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Optional tool gateway intercepts &#x2F; routes &#x2F; authorizes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MCP server receives the call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MCP server translates MCP call into actual backend call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Backend result returns back through the same path. MCP server wraps result into MCP response.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gateway logs&#x2F;redacts&#x2F;validates response.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;MCP client returns tool result to agent runtime.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent uses result in next reasoning step&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Conclusively, tool design is behavior design. MCP standardizes the shape of tool access. The tool gateway governs whether that access should happen.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;failure-taxonomy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#failure-taxonomy&quot; aria-label=&quot;Anchor link for: failure-taxonomy&quot;&gt;failure taxonomy&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Context failure is not just forgetting. It is misprioritization. The model may have the fact, but not treat it as the controlling fact.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Failure mode&lt;&#x2F;th&gt;&lt;th&gt;What it looks like in an agent&lt;&#x2F;th&gt;&lt;th&gt;Engineering mitigation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Position bias&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The model misses facts buried in the middle of a long transcript&lt;&#x2F;td&gt;&lt;td&gt;Put critical state near the end or in a structured state block&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Context dilution&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Relevant facts are present, but drowned by irrelevant text&lt;&#x2F;td&gt;&lt;td&gt;Retrieve focused snippets instead of dumping whole logs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Context pollution&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Tool output, stale plans, or old assumptions bias the next step&lt;&#x2F;td&gt;&lt;td&gt;Clear or summarize bulky tool results; use TTLs and source IDs&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Context clash&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Old and new instructions conflict; model obeys the wrong one&lt;&#x2F;td&gt;&lt;td&gt;Maintain an explicit decision log and supersession rules&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Compaction loss&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Summary drops a tiny but crucial constraint&lt;&#x2F;td&gt;&lt;td&gt;Use schema-based compaction with required fields&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Memory staleness&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Long-term memory recalls a fact that used to be true&lt;&#x2F;td&gt;&lt;td&gt;Store timestamps, provenance, and invalidation rules&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cross-agent divergence&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Multiple agents hold different partial views of the task&lt;&#x2F;td&gt;&lt;td&gt;Prefer shared state ledgers or single-threaded control for precise tasks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Verifier absence&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The answer sounds plausible but no one checks it&lt;&#x2F;td&gt;&lt;td&gt;Add tests, citations, deterministic tools, or external validators&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;As a mantra, use long context for local coherence. Use retrieval for selection. Use memory for persistence. Use verification for correctness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cool-context-engineering&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cool-context-engineering&quot; aria-label=&quot;Anchor link for: cool-context-engineering&quot;&gt;Cool Context Engineering&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Yeah, baby, I’m talking about managing that context window.  Here the goal is to pass the right subset of conversation, state, memories, facts, and tool results. The main active context, or the working memory that is actually in the form of a prompt sent to the model for the action, should contain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the system instructions&lt;&#x2F;li&gt;
&lt;li&gt;the user’s current requests&lt;&#x2F;li&gt;
&lt;li&gt;the recent dialog inputs&lt;&#x2F;li&gt;
&lt;li&gt;the active task states&lt;&#x2F;li&gt;
&lt;li&gt;the retrieved memories&lt;&#x2F;li&gt;
&lt;li&gt;the retrieved documented tool results&lt;&#x2F;li&gt;
&lt;li&gt;the current plan or unresolved to-dos&lt;&#x2F;li&gt;
&lt;li&gt;the output format constraints&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the most expensive memory tier because it’s a working memory tier, and everything here will be competing for attention. This is compaction. When a conversation approaches the context limit, just summarize the critical contents and restart with a compressed context, preserving architectural decisions, unresolved bugs, and important implementation details while dropping redundant tool outputs. there are three levers of compaction - (1) summarization (cheap, lossy), (2) selective truncation (drop old messages, risky), (3) model-native compaction like Codex uses (preserves latent state, best quality). In case there is user data retension problem as calling &#x2F;responses&#x2F;compact endpoint when the token count exceeds auto_compact_limit returning a new, smaller list of input items that represents the conversation, so data is shared to server, we can opaque encrypted_content blob that encodes the model’s latent understanding of everything that happened, and use decryption keys when required. Client integration is an interesting bit here! rather than returning a single response, prefer emitting a stream of typed events with lifecycle markers. This makes partial rendering, error recovery, and audit logging all much easier to implement. Taking example of codex, it runs the App Server inside a provisioned container, a worker checks out the workspace, launches the App Server binary, and maintains a JSON-RPC channel; the browser talks to the backend over HTTP+SSE. The App Server is long-lived process that hosts Codex core threads and exposes them to clients via a bidirectional JSON-RPC protocol over stdio. It acts as both the transport layer and the translation layer between client requests and low-level agent events. This means the agent keeps running even if the browser tab closes, and a reconnecting session can catch up from the persisted thread history. This is the answer to where the state should leave! If we run the agent in the browser tab, the tab closing kills the session. If er run it server-side, you get persistence but need a reconnect mechanism. I think codex answers it best (i am baised maybe, love gpt5.5 on codex tbh). We run server-side, stream events over SSE, persist thread history, that is exactly how I would design any long running job system (like CI pipelines, batch processing, or async workflows).&lt;&#x2F;p&gt;
&lt;p&gt;Next, there could be short-term memory sessions, which could be thread-scoped. It would remember the current conversations or workflows, but it will not necessarily persist forever. It could be a checkpoint-like thread scope checkpoint. The short-term memory would be part of the agent state and would be persisted per conversation thread. There is also a long-term semantic memory, which stores durable facts like Cursor rules; it is a durable fact. There could also be episodic memories to store past experiences and not just facts. It could be in the STAR format. Episodic memories can be used to model successful interactions, and they could be preserved as learning examples. There could also be a procedural memory to store how the agents should be doing things, and maybe an archival memory for the large external searchable store.&lt;&#x2F;p&gt;
&lt;p&gt;Prompt changes are not copy edits. They are behavioral changes. A one-line instruction to be shorter, stricter, or less verbose can reduce reasoning quality if it changes how the model allocates effort. Prompt caching is critical for efficiency, static content (instructions, tools) lives at the front of the prompt so each new turn gets a cache hit on all prior context. Tool ordering bugs cause expensive cache misses.&lt;&#x2F;p&gt;
&lt;p&gt;We can’t treat all context as equal. If the recent chat turns, old memories, code, documentation, metrics definitions, tool outputs, and runtime observations all get thrown into the same prompt, then it’s a spaghetti! Production agents need context hierarchy. A high-precision agent should know which source wins when context conflicts:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Current runtime state&lt;&#x2F;li&gt;
&lt;li&gt;Authoritative source-of-truth systems&lt;&#x2F;li&gt;
&lt;li&gt;Code and lineage&lt;&#x2F;li&gt;
&lt;li&gt;Curated human annotations&lt;&#x2F;li&gt;
&lt;li&gt;Institutional docs&lt;&#x2F;li&gt;
&lt;li&gt;Prior memories&lt;&#x2F;li&gt;
&lt;li&gt;Conversation history&lt;&#x2F;li&gt;
&lt;li&gt;Model prior knowledge&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The agent is not just retrieving context. It is deciding which context is allowed to govern behavior. &lt;em&gt;Bad memory systems store everything. Good memory systems store corrections that would otherwise be rediscovered painfully.&lt;&#x2F;em&gt; the goal of memory is to retain non-obvious corrections, filters, and constraints that are critical for correctness but hard to infer from other layers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;designing-memory-for-agentic-systems&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#designing-memory-for-agentic-systems&quot; aria-label=&quot;Anchor link for: designing-memory-for-agentic-systems&quot;&gt;Designing memory for agentic systems&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The mistake is treating memory as storage. Memory is not storage. Memory is state selection under constraints. The hard problem is not “can we save this conversation?” The hard problem is “should this fact influence the next action?”. The memory, retrieval, verification, latency, privacy, and session boundaries all depend on structured state between agents that I discussed earlier, not vibes.&lt;&#x2F;p&gt;
&lt;p&gt;Things to think about :&lt;&#x2F;p&gt;
&lt;h3 id=&quot;proper-context-retention-strategy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#proper-context-retention-strategy&quot; aria-label=&quot;Anchor link for: proper-context-retention-strategy&quot;&gt;Proper context retention strategy&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;we already discussed that the active context should contain system instructions, current request, recent dialogue, active task state, retrieved memories, tool results, current plan, unresolved TODOs, and output constraints. That is good, but it needs a retention policy: what stays hot, what gets summarized, what gets archived, and what gets dropped. A production agent needs a retention strategy. Every piece of context should be assigned to one of four buckets:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Hot context  - Always included in the next model call.&lt;&#x2F;li&gt;
&lt;li&gt;Warm context  - Included only when relevant to the current task.&lt;&#x2F;li&gt;
&lt;li&gt;Cold context  - Stored externally and retrieved on demand.&lt;&#x2F;li&gt;
&lt;li&gt;Dead context  - Dropped or expired because it is no longer useful, safe, or valid.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Hot context should contain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;system&#x2F;developer instructions&lt;&#x2F;li&gt;
&lt;li&gt;current user request&lt;&#x2F;li&gt;
&lt;li&gt;active task objective&lt;&#x2F;li&gt;
&lt;li&gt;current state ledger&lt;&#x2F;li&gt;
&lt;li&gt;latest decisions&lt;&#x2F;li&gt;
&lt;li&gt;open constraints&lt;&#x2F;li&gt;
&lt;li&gt;recent relevant turns&lt;&#x2F;li&gt;
&lt;li&gt;required output format&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Warm context should contain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;session summary&lt;&#x2F;li&gt;
&lt;li&gt;recent tool results&lt;&#x2F;li&gt;
&lt;li&gt;relevant prior decisions&lt;&#x2F;li&gt;
&lt;li&gt;unresolved subtasks&lt;&#x2F;li&gt;
&lt;li&gt;retrieved memories&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Cold context should contain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;old tool traces&lt;&#x2F;li&gt;
&lt;li&gt;historical conversations&lt;&#x2F;li&gt;
&lt;li&gt;previous artifacts&lt;&#x2F;li&gt;
&lt;li&gt;old retrieved documents&lt;&#x2F;li&gt;
&lt;li&gt;prior task attempts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Dead context should include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;superseded instructions&lt;&#x2F;li&gt;
&lt;li&gt;stale tool outputs&lt;&#x2F;li&gt;
&lt;li&gt;redundant logs&lt;&#x2F;li&gt;
&lt;li&gt;old intermediate plans&lt;&#x2F;li&gt;
&lt;li&gt;failed hypotheses&lt;&#x2F;li&gt;
&lt;li&gt;sensitive data past its retention window&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;retrieval-strategy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#retrieval-strategy&quot; aria-label=&quot;Anchor link for: retrieval-strategy&quot;&gt;Retrieval strategy&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Retrieval is not just vector search. A serious agent needs hybrid retrieval, authority ranking, recency logic, and contradiction handling.  The agent should not remember everything. It should retain the minimum state needed to continue the task correctly. For agent memory, retrieval has to answer four questions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;What is relevant?&lt;&#x2F;li&gt;
&lt;li&gt;What is current?&lt;&#x2F;li&gt;
&lt;li&gt;What is authoritative?&lt;&#x2F;li&gt;
&lt;li&gt;What is safe to show this user?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Vector similarity only answers the first question, and even that imperfectly. A production retrieval strategy should combine:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;recency retrieval for recent turns and latest decisions&lt;&#x2F;li&gt;
&lt;li&gt;semantic retrieval for conceptually related memories&lt;&#x2F;li&gt;
&lt;li&gt;keyword&#x2F;BM25 retrieval for exact IDs, names, errors, files, and commands&lt;&#x2F;li&gt;
&lt;li&gt;entity retrieval for user, project, customer, repo, ticket, or patient-specific facts&lt;&#x2F;li&gt;
&lt;li&gt;temporal retrieval for facts that changed over time&lt;&#x2F;li&gt;
&lt;li&gt;authority ranking for deciding which source wins during conflicts&lt;&#x2F;li&gt;
&lt;li&gt;access filtering before anything enters the prompt&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A useful retrieval score takes care of eviction properly :&lt;&#x2F;p&gt;
&lt;p&gt;score =
semantic_similarity&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;keyword_match&lt;&#x2F;li&gt;
&lt;li&gt;entity_match&lt;&#x2F;li&gt;
&lt;li&gt;recency_boost&lt;&#x2F;li&gt;
&lt;li&gt;source_authority&lt;&#x2F;li&gt;
&lt;li&gt;memory_importance&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;staleness_penalty&lt;&#x2F;li&gt;
&lt;li&gt;contradiction_risk&lt;&#x2F;li&gt;
&lt;li&gt;privacy_risk&lt;&#x2F;li&gt;
&lt;li&gt;token_cost&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Retrieval should happen before context assembly, but permission checks should happen before retrieval results are exposed to the model.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;latency-awareness&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#latency-awareness&quot; aria-label=&quot;Anchor link for: latency-awareness&quot;&gt;Latency awareness&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A production agent needs to know where latency actually lives.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;User query&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query preprocessing (normalize the query, classify intent, extract entities, detect the current task, rewrite the query, or decide whether memory retrieval is even needed), for example, is this asking about the current session or old memory?, is this asking about the current session or old memory? should we retrieve documents, memories, tool logs, or all of them?, is this a cheap edit request that does not need retrieval?, and more. This step is usually cheap if it is rule-based. It becomes expensive if every request calls another LLM just to decide how to retrieve. A good production system should not run the full retrieval pipeline for trivial turns like. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Query embedding (if semantic retrieval is needed, the query has to be embedded, hosted embedding APIs are simpler to operate, adds network latency, can have rate limits, may have variable p95&#x2F;p99 latency, whereas local embedding model has lower network overhead, easier to batch, more infra complexity, consumes CPU&#x2F;GPU resources. For high-throughput systems, embedding can quietly become a bottleneck, especially true when the agent performs multiple retrievals per user turn. - one embedding for the user query, one embedding for rewritten query, one embedding for entity-expanded query, one embedding for hypothetical answer retrieval, and what not. That may improve recall, but it also increases latency and cost.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Vector &#x2F; keyword retrieval (usually fast, but not always free. Latency depends on index size, embedding dimension, ANN setting, network distance to the vector DB, and more)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Metadata filtering (pre-filtering before vector search is usually better for privacy and efficiency)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Reranking (this imprved quality but iws quite costly, - In case of low-risk queries, you can actually not use any re-ranker and use the recency plus metadata plus spectra scores, if it&amp;#39;s a medium-risk query, you can use a light-weight re-ranker, if it&amp;#39;s a high-risk query, you can use a stronger re-ranker plus verifier)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Prompt construction (Does this context improve the next action enough to justify its token and latency cost?)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LLM prefill (Long memory-heavy prompts hurt prefill. Long answers hurt decode.)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LLM generation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Post-processing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Response&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Memory is not free. Every memory layer adds latency:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;reading checkpoints from Postgres&lt;&#x2F;li&gt;
&lt;li&gt;searching a vector DB&lt;&#x2F;li&gt;
&lt;li&gt;running BM25&lt;&#x2F;li&gt;
&lt;li&gt;reranking candidates&lt;&#x2F;li&gt;
&lt;li&gt;fetching documents&lt;&#x2F;li&gt;
&lt;li&gt;decompressing summaries&lt;&#x2F;li&gt;
&lt;li&gt;checking permissions&lt;&#x2F;li&gt;
&lt;li&gt;assembling the prompt&lt;&#x2F;li&gt;
&lt;li&gt;computing the prefill tokens&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A memory system that improves accuracy but adds 2 seconds to every turn may be unusable for interactive agents. A production context assembler needs a budget:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;20–50 ms: load session state&lt;&#x2F;li&gt;
&lt;li&gt;50–150 ms: retrieve recent&#x2F;warm memories&lt;&#x2F;li&gt;
&lt;li&gt;100–300 ms: hybrid search&lt;&#x2F;li&gt;
&lt;li&gt;100–500 ms: reranking, only for high-value tasks&lt;&#x2F;li&gt;
&lt;li&gt;0 ms: skip retrieval if the current turn can be answered from hot state&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The agent should not run the full memory pipeline on every turn. Use Memory routing examples:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“make it shorter” - Use recent turns only. No vector retrieval.&lt;&#x2F;li&gt;
&lt;li&gt;“continue from where we left off” - Use session summary + recent state.&lt;&#x2F;li&gt;
&lt;li&gt;“what did we decide last week?” - Use long-term memory + event-log retrieval.&lt;&#x2F;li&gt;
&lt;li&gt;“run the same analysis as before” - Use episodic memory + artifact references.&lt;&#x2F;li&gt;
&lt;li&gt;“what is the current status?” - Use runtime tools, not old memory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This connects to prefix caching as well. vLLM’s Automatic Prefix Caching reuses KV cache when requests share the same prefix, which means stable prompt layout can reduce redundant prefill computation. Latency-aware memory design also means prompt layout matters.
Put stable content first:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;system instructions&lt;&#x2F;li&gt;
&lt;li&gt;tool schemas&lt;&#x2F;li&gt;
&lt;li&gt;durable project rules&lt;&#x2F;li&gt;
&lt;li&gt;stable memory block
Put volatile content later:&lt;&#x2F;li&gt;
&lt;li&gt;retrieved snippets&lt;&#x2F;li&gt;
&lt;li&gt;current state&lt;&#x2F;li&gt;
&lt;li&gt;current user request&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This improves prefix-cache hit rate. If you inject timestamps, random IDs, or changing retrieval blocks before the stable prefix, you destroy cache reuse.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;privacy-and-data-boundaries&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#privacy-and-data-boundaries&quot; aria-label=&quot;Anchor link for: privacy-and-data-boundaries&quot;&gt;Privacy and data boundaries&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;An agent memory system is dangerous if it turns private data into global context. Every memory needs scope. Memory scope should be explicit:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;user-scoped memory&lt;&#x2F;li&gt;
&lt;li&gt;session-scoped memory&lt;&#x2F;li&gt;
&lt;li&gt;project-scoped memory&lt;&#x2F;li&gt;
&lt;li&gt;organization-scoped memory&lt;&#x2F;li&gt;
&lt;li&gt;tenant-scoped memory&lt;&#x2F;li&gt;
&lt;li&gt;public memory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A memory should never be retrieved into a context unless the current user, session, and task are allowed to see it. Effective memory access = user permissions ∩ tenant boundary ∩ project boundary ∩ data classification policy ∩ tool permission ∩ current task need&lt;&#x2F;p&gt;
&lt;p&gt;Every stored memory should carry metadata:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;memory_id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;type:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;scope:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;owner:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tenant_id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;project_id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;source_event_id:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;created_at:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;last_seen_at:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;valid_until:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sensitivity:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pii: true|false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;retention_policy:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;can_train_on: true|false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;can_cross_session_retrieve: true|false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Memory is not just a product feature. It is a data-governance surface.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;memory-pruning-and-decay&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-pruning-and-decay&quot; aria-label=&quot;Anchor link for: memory-pruning-and-decay&quot;&gt;Memory pruning and decay&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Long-term memory is useful only if it can forget. Without pruning, memory becomes a junk drawer:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;stale preferences&lt;&#x2F;li&gt;
&lt;li&gt;old project decisions&lt;&#x2F;li&gt;
&lt;li&gt;outdated APIs&lt;&#x2F;li&gt;
&lt;li&gt;superseded instructions&lt;&#x2F;li&gt;
&lt;li&gt;duplicate facts&lt;&#x2F;li&gt;
&lt;li&gt;temporary constraints&lt;&#x2F;li&gt;
&lt;li&gt;failed assumptions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Each memory should have a lifecycle:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Candidate memory - Extracted from a conversation or tool result.&lt;&#x2F;li&gt;
&lt;li&gt;Validated memory - Passed checks for usefulness, scope, and sensitivity.&lt;&#x2F;li&gt;
&lt;li&gt;Active memory - Eligible for retrieval.&lt;&#x2F;li&gt;
&lt;li&gt;Decaying memory - Still stored but receives a lower retrieval score.&lt;&#x2F;li&gt;
&lt;li&gt;Superseded memory - Replaced by a newer fact.&lt;&#x2F;li&gt;
&lt;li&gt;Archived memory - Searchable only in explicit historical queries.&lt;&#x2F;li&gt;
&lt;li&gt;Deleted memory - Removed because it is unsafe, expired, or user-requested.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;retrieval_priority =
importance&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;frequency_of_use&lt;&#x2F;li&gt;
&lt;li&gt;recency&lt;&#x2F;li&gt;
&lt;li&gt;source_authority&lt;&#x2F;li&gt;
&lt;li&gt;user_confirmation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ul&gt;
&lt;li&gt;age_penalty&lt;&#x2F;li&gt;
&lt;li&gt;contradiction_penalty&lt;&#x2F;li&gt;
&lt;li&gt;sensitivity_penalty&lt;&#x2F;li&gt;
&lt;li&gt;low_usage_penalty&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Pruning jobs should run periodically:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;merge duplicate memories&lt;&#x2F;li&gt;
&lt;li&gt;delete low-value memories&lt;&#x2F;li&gt;
&lt;li&gt;downgrade stale memories&lt;&#x2F;li&gt;
&lt;li&gt;mark superseded memories&lt;&#x2F;li&gt;
&lt;li&gt;refresh memories from source-of-truth systems&lt;&#x2F;li&gt;
&lt;li&gt;remove memories past retention limits&lt;&#x2F;li&gt;
&lt;li&gt;detect contradictions between old and new facts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Do not let the model silently create permanent memory from every conversation. Memory write policy:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ephemeral session fact: auto-write&lt;&#x2F;li&gt;
&lt;li&gt;project decision: write with provenance&lt;&#x2F;li&gt;
&lt;li&gt;user preference: write if repeated or confirmed&lt;&#x2F;li&gt;
&lt;li&gt;sensitive personal data: require explicit consent&lt;&#x2F;li&gt;
&lt;li&gt;procedural rule: require human review&lt;&#x2F;li&gt;
&lt;li&gt;security&#x2F;medical&#x2F;legal rule: never silently write&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;sessions-need-hard-boundaries&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sessions-need-hard-boundaries&quot; aria-label=&quot;Anchor link for: sessions-need-hard-boundaries&quot;&gt;Sessions need hard boundaries&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A session is not just a chat window. A session defines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;what the agent is trying to do&lt;&#x2F;li&gt;
&lt;li&gt;what state is currently active&lt;&#x2F;li&gt;
&lt;li&gt;which tool results are relevant&lt;&#x2F;li&gt;
&lt;li&gt;which temporary assumptions are valid&lt;&#x2F;li&gt;
&lt;li&gt;which memories are allowed to influence behavior&lt;&#x2F;li&gt;
&lt;li&gt;when the workflow is over&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Session types:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Single-turn session - No durable memory. Answer and forget.&lt;&#x2F;li&gt;
&lt;li&gt;Multi-turn chat session - Keep recent turns, active preferences, and local context.&lt;&#x2F;li&gt;
&lt;li&gt;Long-running workflow session - Persist checkpoints, state ledger, artifacts, tool results, and resumable progress.&lt;&#x2F;li&gt;
&lt;li&gt;Project session - Share selected memory across multiple workflows.&lt;&#x2F;li&gt;
&lt;li&gt;Cross-session user memory - Store stable user preferences and durable facts only.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;When a session ends, the system should decide:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What should be summarized?&lt;&#x2F;li&gt;
&lt;li&gt;What should become durable memory?&lt;&#x2F;li&gt;
&lt;li&gt;What should remain only in the raw event log?&lt;&#x2F;li&gt;
&lt;li&gt;What should be deleted?&lt;&#x2F;li&gt;
&lt;li&gt;What should be hidden from future sessions?&lt;&#x2F;li&gt;
&lt;li&gt;What should require user approval before persistence?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Add a concrete session closeout schema:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;session_closeout:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  objective_completed: true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  final_state_summary: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  durable_decisions:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  user_preferences_detected:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - preference: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      confidence: 0.72&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      write_policy: ask_user&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  artifacts_created:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - id: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      type: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      location: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  memories_to_create:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - content: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      scope: project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ttl: 90_days&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      provenance: event_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  memories_to_expire:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - memory_id: &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      reason: superseded&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  unresolved_items:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    - &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If someone asks, “How would you design memory for an agentic AI system?”, the answer should not be “I’ll just store the chat history.” A production memory system needs layers. I would start with short-term session memory for the current task: recent turns, active goals, open constraints, intermediate tool results, and the current state ledger. This is the agent’s working memory. Then I would add entity-scoped memory for durable facts about users, projects, organizations, repositories, tickets, customers, patients, or other domain objects. These facts should not live as vague text blobs. They should have metadata: source, timestamp, owner, tenant, confidence, sensitivity, and validity window. Then I would add retrieval-gated long-term memory. Older conversations, tool traces, decisions, summaries, and artifacts should be stored externally and retrieved only when relevant. Retrieval should use semantic search, keyword search, entity filters, recency, and source authority — not just top-k vector similarity. I would write to memory conservatively. Not every conversation turn deserves to become permanent memory. Temporary assumptions should stay in the session. Durable facts should require confidence, provenance, and the right scope. Sensitive or high-impact memories should require user approval or policy checks before being persisted. At read time, I would retrieve with strict metadata filters. Only after those boundaries are enforced would I run semantic retrieval and reranking. I might use a relevance threshold such as 0.7, but that threshold should be calibrated against evals, not chosen blindly. Below the threshold, the memory should not enter the prompt. I would also make memory decay over time. Entity facts could age on a 30-day half-life unless reaffirmed. Old preferences, stale project decisions, deprecated APIs, and superseded tool results should gradually lose retrieval priority. If a newer source contradicts an older memory, the older one should be marked superseded instead of being retrieved as if it were still true. Finally, I would namespace memory by tenant, user, project, and session at the read boundary. The agent should never retrieve memory across privacy boundaries just because the embedding search says it is similar. Memory is not just storage. It is a permissioned, time-aware, relevance-gated state system. A good agent memory system is conservative on writes, strict on reads, aware of time, aware of privacy, and optimized for the current task. It remembers enough to be useful, forgets enough to stay correct, and never lets stale or unauthorized context silently steer the agent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;do-you-real-y-know-your-agent&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#do-you-real-y-know-your-agent&quot; aria-label=&quot;Anchor link for: do-you-real-y-know-your-agent&quot;&gt;Do you real;y know your agent?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;engineering&#x2F;demystifying-evals-for-ai-agents&quot;&gt;A complete understanding of agents requires automated evals, production monitoring, A&#x2F;B testing, user feedback, manual transcript review, and systematic human studies rather than a single metric.&lt;&#x2F;a&gt;. We need to observe state transitions, not just the final response! What context was selected? What evidence was retrieved? What tool was called? What arguments were passed? What state changed? What verifier ran? What constraint was dropped? What grader made the final judgment? An eval score without a trace is almost useless for agent engineering! We need a debugging surface, not just a score.&lt;&#x2F;p&gt;
&lt;p&gt;Basically when the agent stops being predictable, and there is fall in accuracy and lots of hallucinations, it’s often a failure in the environment, or more precisely, in the system that supports the agent. Not everything is about tweaking models, at this point they are really powerful. You’re spending real money on LLM calls, your LangSmith dashboard is filling up with traces, but still you can’t confidently answer basic questions about where your budget is actually going. Which calls are wasteful? Which prompts are bloated? Is that expensive run the norm or an outlier? You have hundreds of traces and gigabytes of span data, but there’s no easy way to query across it. Agent evals are not just benchmarks or worse a leaderboard number, they are observability systems. A useful agent eval should produce a structured trace: what context the model saw, which memories were retrieved, which tools were called, what arguments were used, what state changed, what verifier ran, what grader scored the output, and which exact version of the model&#x2F;prompt&#x2F;tool schema produced the result. The question is not only “did the agent pass?” The question is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Did it see the right evidence?&lt;&#x2F;li&gt;
&lt;li&gt;Did it use the evidence?&lt;&#x2F;li&gt;
&lt;li&gt;Did it call the right tool?&lt;&#x2F;li&gt;
&lt;li&gt;Did the tool return the right state?&lt;&#x2F;li&gt;
&lt;li&gt;Did compaction drop a constraint?&lt;&#x2F;li&gt;
&lt;li&gt;Did memory inject stale information?&lt;&#x2F;li&gt;
&lt;li&gt;Did the grader reject a valid solution?&lt;&#x2F;li&gt;
&lt;li&gt;Did infra noise change the result?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;eval-driven dev maybe? task-specific evals, logging everything so logs can become eval cases, continuous evaluation, and calibrating automated scoring with human judgment.&lt;&#x2F;p&gt;
&lt;p&gt;Telemetry schema I used in one of my past projects :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;val_run&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;val_suite&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ataset_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ask_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ask_family&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ifficulty&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;reated_at&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ystem_under_test&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;odel&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;odel_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rompt_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ool_schema_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etrieval_index_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;emory_policy_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ompaction_policy_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;gent_harness_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ampling&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;emperature&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;op_p&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ax_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext_trace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nput_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;utput_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontext_window&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ystem_prompt_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ool_definition_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;emory_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etrieval_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;onversation_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ummary_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;runcated_items&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etrieved_items&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ource&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;core&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ncluded&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;eason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ompaction_events&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;efore_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;fter_tokens&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;reserved_fields&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ropped_fields&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;gent_trace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;urns&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ool_calls&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;all_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ool&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rgs_hash&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tatus&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uccess|error|timeout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atency_ms&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ide_effect_summary&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;andoffs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;etries&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;top_reason&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tate_trace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nitial_state_hash&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;inal_state_hash&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tate_diff&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;iles_changed&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atabase_changes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;xternal_side_effects&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rader_trace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;raders&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ode|model|human|state_check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;core&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ass&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ationale_summary&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  j&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;udge_model&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ubric_version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uman_labeler_id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rader_disagreement&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;untime_trace&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  l&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;atency_ms&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ost_usd&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;rovider&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;egion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ardware&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ontainer_image&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;imeout_ms&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  m&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;emory_limit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;pu_limit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  i&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;nfra_errors&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;utcome&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ass&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  f&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ailure_category&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;otes&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This schema makes failures queryable. You can ask: “Show me all failures where the right document was retrieved but not cited,” “Show me all failures after compaction,” “Show me all retries caused by one tool,” or “Show me tasks where the grader and human disagreed.” &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;specs&#x2F;semconv&#x2F;gen-ai&#x2F;&quot;&gt;OpenTelemetry is moving toward this kind of standardized instrumentation for generative AI, its GenAI conventions define spans, metrics, events, model spans, agent spans, and provider-specific conventions, and its GenAI span spec includes attributes such as operation name, provider, model, conversation ID, output type, and error type.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;btw, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.anthropic.com&#x2F;engineering&#x2F;infrastructure-noise&quot;&gt;agent evals are infrastructure-sensitive&lt;&#x2F;a&gt;! A model can score differently because of container memory, CPU limits, dependency installation, timeout policy, sandbox provider, cache state, or serving configuration. If the eval harness is not controlled, you may be benchmarking infrastructure headroom rather than intelligence. So, we should log resource limits, timeout policy, container image, dependency state, hardware class, cache state, model version, harness version, and retry policy, in production systems.&lt;&#x2F;p&gt;
&lt;p&gt;core quality and reliability metrics :&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;&#x2F;th&gt;&lt;th&gt;What it tells you&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Pass rate&lt;&#x2F;td&gt;&lt;td&gt;Overall success&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Pass@k &#x2F; pass^k&lt;&#x2F;td&gt;&lt;td&gt;Reliability across repeated attempts&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Failure category&lt;&#x2F;td&gt;&lt;td&gt;What kind of thing broke&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Context tokens by source&lt;&#x2F;td&gt;&lt;td&gt;Whether memory&#x2F;retrieval&#x2F;tool logs are bloating context&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Relevant evidence included?&lt;&#x2F;td&gt;&lt;td&gt;Whether retrieval&#x2F;context assembly worked&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Relevant evidence used?&lt;&#x2F;td&gt;&lt;td&gt;Whether the model grounded its action&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tool-call precision&lt;&#x2F;td&gt;&lt;td&gt;Whether tool calls were necessary and correct&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tool-call recall&lt;&#x2F;td&gt;&lt;td&gt;Whether required tools were skipped&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Duplicate tool-call rate&lt;&#x2F;td&gt;&lt;td&gt;Whether the agent is looping or forgetting&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;State-diff correctness&lt;&#x2F;td&gt;&lt;td&gt;Whether the external world ended correctly&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Compaction survival rate&lt;&#x2F;td&gt;&lt;td&gt;Whether summaries preserve required constraints&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Grader disagreement&lt;&#x2F;td&gt;&lt;td&gt;Whether the scoring method is unstable&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Human&#x2F;LLM judge agreement&lt;&#x2F;td&gt;&lt;td&gt;Whether automated grading is calibrated&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;p50&#x2F;p95&#x2F;p99 latency&lt;&#x2F;td&gt;&lt;td&gt;Whether quality changes trade off against UX&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cost per successful task&lt;&#x2F;td&gt;&lt;td&gt;Whether the agent is economically viable&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Infra error rate&lt;&#x2F;td&gt;&lt;td&gt;Whether failures are model failures or system failures&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Slice performance&lt;&#x2F;td&gt;&lt;td&gt;Which task families regress&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;context specific :&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Eval&lt;&#x2F;th&gt;&lt;th&gt;How to run it&lt;&#x2F;th&gt;&lt;th&gt;Failure detected&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Position sweep&lt;&#x2F;td&gt;&lt;td&gt;Move the same key fact to beginning&#x2F;middle&#x2F;end of context&lt;&#x2F;td&gt;&lt;td&gt;Lost-in-the-middle &#x2F; position bias&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Distractor injection&lt;&#x2F;td&gt;&lt;td&gt;Add irrelevant but plausible tool logs&lt;&#x2F;td&gt;&lt;td&gt;Context dilution&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Contradiction update&lt;&#x2F;td&gt;&lt;td&gt;Old instruction says A; later valid decision says B&lt;&#x2F;td&gt;&lt;td&gt;Stale-state obedience&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Compaction survival&lt;&#x2F;td&gt;&lt;td&gt;Force summary, then test old constraint&lt;&#x2F;td&gt;&lt;td&gt;Summary loss&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Memory staleness&lt;&#x2F;td&gt;&lt;td&gt;Store old fact, then supersede it&lt;&#x2F;td&gt;&lt;td&gt;Bad long-term memory invalidation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Tool deduplication&lt;&#x2F;td&gt;&lt;td&gt;Give prior tool result, see if agent repeats call&lt;&#x2F;td&gt;&lt;td&gt;Forgetful loops&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Handoff test&lt;&#x2F;td&gt;&lt;td&gt;Move task between agents&lt;&#x2F;td&gt;&lt;td&gt;Cross-agent state loss&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Long-run pass^k&lt;&#x2F;td&gt;&lt;td&gt;Run the same task repeatedly across long trajectories&lt;&#x2F;td&gt;&lt;td&gt;Reliability, not one-off success&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;For agents, cost&#x2F;request is less useful than cost&#x2F;successful task. A cheaper model that loops, repeats tool calls, or fails silently can be more expensive than a stronger model that finishes once.&lt;&#x2F;p&gt;
&lt;p&gt;You cannot know whether an agent improved unless you test it against known cases.&lt;&#x2F;p&gt;
&lt;p&gt;For deterministic software, we write unit tests.&lt;&#x2F;p&gt;
&lt;p&gt;For agents, we need evals:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;golden questions&lt;&#x2F;li&gt;
&lt;li&gt;expected tool calls&lt;&#x2F;li&gt;
&lt;li&gt;expected source selection&lt;&#x2F;li&gt;
&lt;li&gt;expected final result&lt;&#x2F;li&gt;
&lt;li&gt;acceptable reasoning path&lt;&#x2F;li&gt;
&lt;li&gt;unacceptable failure modes&lt;&#x2F;li&gt;
&lt;li&gt;semantic graders, not string matching&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The eval should not only ask, “Was the final answer plausible?”&lt;&#x2F;p&gt;
&lt;p&gt;It should ask:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Did the agent choose the right source?&lt;&#x2F;li&gt;
&lt;li&gt;Did it retrieve the right context?&lt;&#x2F;li&gt;
&lt;li&gt;Did it use the right filter?&lt;&#x2F;li&gt;
&lt;li&gt;Did it avoid stale memory?&lt;&#x2F;li&gt;
&lt;li&gt;Did it detect bad intermediate results?&lt;&#x2F;li&gt;
&lt;li&gt;Did it cite the correct evidence?&lt;&#x2F;li&gt;
&lt;li&gt;Did it escalate when uncertain?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;llm-as-a-judge&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#llm-as-a-judge&quot; aria-label=&quot;Anchor link for: llm-as-a-judge&quot;&gt;llm as a judge&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I’m not very keen on this, but it simply is like using a strong model to evaluate a weaker model’s output. In here, there is often a loss of diversity if you do LLM as a judge. Considering other things, how common it is being used, it’s more important to have a good scoring prompt than the model itself. A vague prompt like “simply rate this response” will produce a very noisy score. A structured prompt with rubrics will produce consistent, reproducible scores, but there are a lot of failure modes in this as well.&lt;&#x2F;p&gt;
&lt;p&gt;Judge models often exhibit position bias, i.e., they prefer the first response in the pair-wise comparisons. There is a verbosity bias as well, so it prefers longer responses, and there are weird self-preferences like GPT 5.5 would rate GPT 5.5 higher than the equivalent Claude Opus 4.7 outputs. To minimize that, you can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;use randomization of order&lt;&#x2F;li&gt;
&lt;li&gt;normalize for the length&lt;&#x2F;li&gt;
&lt;li&gt;use a different judge than the model being evaluated&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The famous RAGAS is there as an evaluation framework specifically for RAG pipelines, which measures the faithfulness, relevance and the answer correctness? So that’s there as well if you are playing with RAG Pipelines.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, there is something called prompt foo as well, so it’s a config-driven eval for prompt engineering. What it does is it simply defines test cases in YAML and runs against multiple models and gets a pass&#x2F;fail report. Often used for regression test prompts, so that a prompt change does not break the existing test cases&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-agent-should-never-be-more-authorized-than-the-user&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-agent-should-never-be-more-authorized-than-the-user&quot; aria-label=&quot;Anchor link for: the-agent-should-never-be-more-authorized-than-the-user&quot;&gt;The agent should never be more authorized than the user&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A production agent is not a magic superuser. It should inherit the user’s permissions, not bypass them. The security rule is simple:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Agent access = user permissions ∩ tool permissions ∩ policy permissions.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If a user cannot read a table, document, patient record, ticket, or customer account directly, the agent should not be able to retrieve it on their behalf. This matters because agents combine information. Without pass-through permissions, an agent can accidentally become a data exfiltration system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-harness&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#running-harness&quot; aria-label=&quot;Anchor link for: running-harness&quot;&gt;running harness&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;codex has everything, CLI, a web app, and a macOS desktop app, all with underlying harness that is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codex.danielvaughan.com&#x2F;2026&#x2F;04&#x2F;07&#x2F;codex-cli-agentic-loop-internals&#x2F;&quot;&gt;a Rust lib containing the agent loop, thread lifecycle (create&#x2F;resume&#x2F;fork&#x2F;archive), config and auth management, and sandboxed tool execution&lt;&#x2F;a&gt;. the harness manages the full lifecycle of one conversation thread, including persisting the event history so clients can reconnect and render a consistent timeline, a stable protocol that exposes this runtime to any client, language or platform agnostic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;memory-systems-decay&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-systems-decay&quot; aria-label=&quot;Anchor link for: memory-systems-decay&quot;&gt;memory systems decay&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A very subtle failure mode in agentic systems is embedding-space drift. Teams often treat embeddings as timeless. They are not. A vector is only meaningful relative to the model, preprocessing pipeline, chunking strategy, normalization method, and distance function that produced it. If the document vectors were created with one embedding model and the user query is embedded with another, search quality can silently degrade. The system may still run. The vector DB may still return results. Nothing throws an error. But recall gets worse, the wrong chunks appear near the top, and users start saying the agent “feels dumber.”&lt;&#x2F;p&gt;
&lt;p&gt;OpenAI’s current embedding docs, for example, distinguish text-embedding-3-small and text-embedding-3-large, with different default vector lengths, and also support shortening embeddings using a dimensions parameter. That means model choice and dimensionality are part of the retrieval contract, not incidental implementation details.&lt;&#x2F;p&gt;
&lt;p&gt;Every embedded object should carry version metadata:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;embedding_model&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text-embedding-3-large&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;embedding_model_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2026-05-embedding-config-v2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;dimensions&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;distance&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cosine&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;chunker_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;semantic-chunker-v4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;preprocessing_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;html-cleaner-v3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;created_at&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2026-05-21T10:00:00Z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;source_doc_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;doc_982:v17&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Embedding model migration should be treated like a database migration, not a casual config change.
A safe embedding migration looks like this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Pin the current embedding model and index config.&lt;&#x2F;li&gt;
&lt;li&gt;Create a new vector collection for the new embedding model.&lt;&#x2F;li&gt;
&lt;li&gt;Dual-write new documents to both old and new collections.&lt;&#x2F;li&gt;
&lt;li&gt;Backfill old documents by re-embedding from source text.&lt;&#x2F;li&gt;
&lt;li&gt;Run shadow retrieval against both indexes.&lt;&#x2F;li&gt;
&lt;li&gt;Compare recall, MRR, nDCG, answer quality, and latency.&lt;&#x2F;li&gt;
&lt;li&gt;Canary the new index on a small percentage of traffic.&lt;&#x2F;li&gt;
&lt;li&gt;Roll forward only if evals and production metrics improve.&lt;&#x2F;li&gt;
&lt;li&gt;Keep rollback available until confidence is high.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Do not overwrite the old vectors in place! bad idea, do the canary deployment.&lt;&#x2F;p&gt;
&lt;p&gt;Old and new embedding spaces should coexist during migration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;evals-that-evolve&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#evals-that-evolve&quot; aria-label=&quot;Anchor link for: evals-that-evolve&quot;&gt;evals that evolve&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The hard part of evals is rarely the harness. The hard part is building the dataset, discovering edge cases, comparing configurations, understanding failures, and continuously updating the suite as the system changes. A real eval process is iterative:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;collect real user questions&lt;&#x2F;li&gt;
&lt;li&gt;label expected behavior&lt;&#x2F;li&gt;
&lt;li&gt;run multiple retrieval&#x2F;model&#x2F;tool configurations&lt;&#x2F;li&gt;
&lt;li&gt;compare outputs&lt;&#x2F;li&gt;
&lt;li&gt;inspect low-scoring cases&lt;&#x2F;li&gt;
&lt;li&gt;identify failure patterns&lt;&#x2F;li&gt;
&lt;li&gt;add new test cases&lt;&#x2F;li&gt;
&lt;li&gt;improve retrieval, memory, prompts, tools, or policies&lt;&#x2F;li&gt;
&lt;li&gt;rerun the suite&lt;&#x2F;li&gt;
&lt;li&gt;repeat&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;An agentic eval should test more than the final answer. It should evaluate:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;retrieval quality&lt;&#x2F;li&gt;
&lt;li&gt;memory selection&lt;&#x2F;li&gt;
&lt;li&gt;tool choice&lt;&#x2F;li&gt;
&lt;li&gt;tool arguments&lt;&#x2F;li&gt;
&lt;li&gt;permission handling&lt;&#x2F;li&gt;
&lt;li&gt;intermediate state updates&lt;&#x2F;li&gt;
&lt;li&gt;structured handoffs between agents&lt;&#x2F;li&gt;
&lt;li&gt;verifier behavior&lt;&#x2F;li&gt;
&lt;li&gt;abstention behavior&lt;&#x2F;li&gt;
&lt;li&gt;final answer quality&lt;&#x2F;li&gt;
&lt;li&gt;latency and cost&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The next frontier is evals that detect their own obsolescence. An eval suite becomes obsolete when production behavior changes but the eval set does not. If users start asking new kinds of questions, tools change, documents change, policies change, or the agent starts failing in a new way, the eval suite should notice that its coverage is no longer enough.&lt;&#x2F;p&gt;
&lt;p&gt;An eval suite can become stale when:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;production queries no longer look like eval queries&lt;&#x2F;li&gt;
&lt;li&gt;new tools are added but not tested&lt;&#x2F;li&gt;
&lt;li&gt;new document types enter the corpus&lt;&#x2F;li&gt;
&lt;li&gt;user behavior changes&lt;&#x2F;li&gt;
&lt;li&gt;policies change&lt;&#x2F;li&gt;
&lt;li&gt;retrieval index changes&lt;&#x2F;li&gt;
&lt;li&gt;memory format changes&lt;&#x2F;li&gt;
&lt;li&gt;new failure modes appear in logs&lt;&#x2F;li&gt;
&lt;li&gt;old “golden answers” become outdated&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A stale eval suite gives false confidence. The dashboard stays green while production quality gets worse.&lt;&#x2F;p&gt;
&lt;p&gt;A modern agentic eval system should monitor:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Query distribution drift - Are production questions still similar to eval questions?&lt;&#x2F;li&gt;
&lt;li&gt;Tool-use drift - Is the agent using tools in ways the eval suite does not cover?&lt;&#x2F;li&gt;
&lt;li&gt;Retrieval drift - Are retrieved sources changing? Are top-k results less relevant than before?&lt;&#x2F;li&gt;
&lt;li&gt;Memory drift - Are stale memories entering prompts? Are useful memories being missed?&lt;&#x2F;li&gt;
&lt;li&gt;Failure-cluster drift - Are new classes of failures appearing in production traces?&lt;&#x2F;li&gt;
&lt;li&gt;Human-feedback drift - Are users correcting the agent on issues that are absent from evals?&lt;&#x2F;li&gt;
&lt;li&gt;Cost&#x2F;latency drift - Did a configuration improve accuracy but make the system too slow?&lt;&#x2F;li&gt;
&lt;li&gt;Policy drift - Did product, legal, clinical, or security requirements change?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A production loop could be :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The eval loop should look like this:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;production traces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;failure clustering&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;candidate eval generation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;human review &#x2F; labeling&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;eval suite update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;configuration comparison&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;regression gate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;deployment canary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ↓&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;monitoring&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;conclusion-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion-1&quot; aria-label=&quot;Anchor link for: conclusion-1&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A production agent does not only need memory. It needs memory operations. That means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;embedding-space versioning&lt;&#x2F;li&gt;
&lt;li&gt;index migration plans&lt;&#x2F;li&gt;
&lt;li&gt;retrieval quality monitoring&lt;&#x2F;li&gt;
&lt;li&gt;evals for retrieval and generation&lt;&#x2F;li&gt;
&lt;li&gt;failure clustering&lt;&#x2F;li&gt;
&lt;li&gt;dataset refresh workflows&lt;&#x2F;li&gt;
&lt;li&gt;shadow runs and canaries&lt;&#x2F;li&gt;
&lt;li&gt;rollback paths&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Multi-agent systems are attractive because they look like organizations: researcher, planner, coder, reviewer, manager. But splitting work across agents also splits context. Each handoff can drop assumptions, hide tool observations, or create conflicting local plans. Multi-agent architecture helps when the task naturally decomposes and each agent has a clean contract. It hurts when correctness depends on a shared, evolving state. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cognition.ai&#x2F;blog&#x2F;dont-build-multi-agents&quot;&gt;Maybe, don’t use multi-agents if you don’t really need it?&lt;&#x2F;a&gt; Use subagents for bounded questions, not uncontrolled ownership. A subagent can inspect a file, search a corpus, or produce a critique. But the main controller should own the state ledger, decisions, and final action.&lt;&#x2F;p&gt;
&lt;p&gt;The future of reliable agents is not just bigger context windows. It is better context discipline. The agent that wins is not the one that can read the longest transcript; it is the one that knows what state matters, what evidence supports it, what assumptions are stale, what actions changed the world, and what must be verified before answering. Long context is useful. But correctness comes from state, selection, and verification.&lt;&#x2F;p&gt;
&lt;p&gt;The best production agents are not prompt chains. They are context systems. A production-grade agent usually has:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Layered context - It separates schema, code, docs, memory, runtime state, and user conversation instead of merging everything into one blob.&lt;&#x2F;li&gt;
&lt;li&gt;Source authority - It knows which source wins when two pieces of context conflict.&lt;&#x2F;li&gt;
&lt;li&gt;Code or system-grounded semantics - It learns meaning from the systems that produce the data, not just from documentation.&lt;&#x2F;li&gt;
&lt;li&gt;Closed-loop reasoning - It checks intermediate results, detects anomalies, and retries before answering.&lt;&#x2F;li&gt;
&lt;li&gt;Scoped memory - It stores non-obvious corrections and constraints, not the whole transcript.&lt;&#x2F;li&gt;
&lt;li&gt;Tool discipline - It uses fewer, clearer tools with well-defined contracts.&lt;&#x2F;li&gt;
&lt;li&gt;Continuous evals - It has golden cases, regression tests, semantic graders, and production canaries.&lt;&#x2F;li&gt;
&lt;li&gt;Pass-through permissions - It never gives the agent more access than the user already has.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is why long-context alone does not solve agents. A giant context window gives the model more tokens. A production context system gives the model the right facts, in the right order, with the right authority, under the right constraints.&lt;&#x2F;p&gt;
&lt;p&gt;The agent will decay unless the memory system and eval system evolve with it. RAG systems rot when embeddings, documents, user behavior, and tools change but the index and evals stay frozen.
The goal is not just to build an eval suite. The goal is to build an eval system that tells you when it no longer represents reality.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>DB Joins on GPUs!!</title>
          <pubDate>Thu, 26 Feb 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/db-joins-on-gpus/</link>
          <guid>https://harsh-ps-2003.github.io/writes/db-joins-on-gpus/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/db-joins-on-gpus/">&lt;p&gt;I was studying for my High Performance Computing Exams sometime ago, and interestingly, I stumbled upon a slide stating that H100 GPU can do 15 queries&#x2F;sec and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nvidia.com&#x2F;en-in&#x2F;data-center&#x2F;gb200-nvl72&#x2F;&quot;&gt;GB200NVL72&lt;&#x2F;a&gt; can do whopping 90 queries&#x2F;sec compared to just 5 queries&#x2F;sec on typical x86 architectures. Never thought about this, so digged deep out of curiosity.&lt;&#x2F;p&gt;
&lt;p&gt;The idea of GPU hash joins emerged in 2008 academia to harness GPUs’ massive thread parallelism and memory bandwidth for data-intensive OLAP joins, which were memory-bound on CPUs. Bin He et al. pioneered it in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cse.iitb.ac.in&#x2F;infolab&#x2F;Data&#x2F;Courses&#x2F;CS632&#x2F;2017&#x2F;2015&#x2F;Papers&#x2F;sigmod08-GPU-he.pdf&quot;&gt;Relational Joins on Graphics Processors&lt;&#x2F;a&gt;, implementing the first GPU hash join kernel—up to 100x faster than CPU for 1B-row joins via parallel radix partitioning and atomic inserts.&lt;&#x2F;p&gt;
&lt;p&gt;Yess, SQL joins can run very efficiently on GPUs by exploiting massive data parallelism, usually via hash joins or sort‑merge joins that are rewritten as GPU kernels.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-core-idea&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-core-idea&quot; aria-label=&quot;Anchor link for: the-core-idea&quot;&gt;The Core Idea&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A join is just a big comparison between rows of two tables: for each key in table A, find matching keys in table B. GPUs are ideal because you can give each row (or chunk of rows) to a separate thread and run tens of thousands of these comparisons in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;Traditional CPU hash joins process tables serially: build a hash table from smaller table A (one key at a time), then probe larger table B sequentially. This is memory-bound—hash lookups hit DRAM cache misses constantly. GPUs flip this by launching 10k-100k+ threads simultaneously: all keys from table A hash&#x2F;insert in parallel during build (using atomic operations to resolve collisions), then all keys from table B probe in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;Most joins are equi-joins, which use only equality comparisons in the join-predicate. Hash joins are the most important equi-join physical implemenations in the analytical world.&lt;&#x2F;p&gt;
&lt;p&gt;Hash join taking advantage of GPUs would typically involves two steps:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build phase: Use many GPU threads to build a hash table from the smaller input relation in GPU memory. Load the smaller table (build input) into GPU HBM. Launch thousands of threads (e.g., 10^5+ on H100) where each hashes a key and atomically inserts into a GPU hash table (using libraries like cuCollections for synchronization). Shared memory caches frequent accesses to minimize global memory latency&lt;&#x2F;li&gt;
&lt;li&gt;Probe phase: Other threads scan the larger table; each row hashes its join key and probes the hash table to find matches&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This parallelism exploits GPU’s 3 TB&#x2F;s HBM bandwidth vs. CPU DRAM’s ~100 GB&#x2F;s.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gpu-dbs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#gpu-dbs&quot; aria-label=&quot;Anchor link for: gpu-dbs&quot;&gt;GPU DBs&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GPU‑native databases like HeavyDB and Kinetica compile SQL queries (including equi‑joins, multi‑way joins) into GPU kernels that execute these parallel hash or sort‑merge joins over columnar data layouts. They keep hot columns compressed and resident in GPU memory when possible, and otherwise stream partitions from CPU RAM to GPU HBM while overlapping transfer and join computation.&lt;&#x2F;p&gt;
&lt;p&gt;HeavyDB on a single GPU outperforms CPU warehouses (Snowflake, BigQuery) by 6-190x on geospatial joins with 100M+ rows, completing in milliseconds what takes hours on CPU due to nested loops. Kinetica supports multi-table joins, offloading to GPUs for 100x analytics speedups via NVLink data streaming. Crazyyyyy&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;GPU-accelerated hash joins shine in high-volume OLAP workloads where massive parallelism slashes query times from minutes&#x2F;hours to milliseconds, but they’re unnecessary for small datasets or transactional OLTP.&lt;&#x2F;p&gt;
&lt;p&gt;Just go through &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2406.13831v1&quot;&gt;a comprehensive overview of GPU DBs&lt;&#x2F;a&gt; if more curious about the paradigm.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Which Prompts Actually Work for your Agents?</title>
          <pubDate>Sun, 22 Feb 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/which-prompts-actually-work-for-your-agents/</link>
          <guid>https://harsh-ps-2003.github.io/writes/which-prompts-actually-work-for-your-agents/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/which-prompts-actually-work-for-your-agents/">&lt;p&gt;I was wondering on a lazy sunday, which parts of my prompt actually matter?&lt;&#x2F;p&gt;
&lt;p&gt;Agents (ReAct, tool-calling, multi-step reasoning) depend heavily on system prompts: role, rules, tool descriptions, few-shot examples. It’s easy to bloat them and hard to know what’s redundant. So, I found out about &lt;strong&gt;Saliency analysis&lt;&#x2F;strong&gt; which gives you numbers, perturb each phrase, see how much the agent’s output changes. High change → that phrase matters; low change → candidate to cut or simplify. So, the goal is to find which parts of your agent’s system prompt actually drive behaviour, then trim the rest and protect what matters. Simple, yet I don’t see a lot of people using it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-is-a-sensitive-issue&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-is-a-sensitive-issue&quot; aria-label=&quot;Anchor link for: this-is-a-sensitive-issue&quot;&gt;This is a sensitive issue&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Recent research has quantified just how sensitive LLMs are to prompt formulation. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2310.11324&quot;&gt;LLMs show extreme sensitivity to subtle changes in prompt formatting&lt;&#x2F;a&gt;, even after instruction tuning and scaling.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2410.12405&quot;&gt;ProSA framework&lt;&#x2F;a&gt; established that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt sensitivity fluctuates unpredictably across datasets and models&lt;&#x2F;li&gt;
&lt;li&gt;Larger models demonstrate enhanced robustness, but not immunity&lt;&#x2F;li&gt;
&lt;li&gt;Few-shot examples can alleviate sensitivity issues&lt;&#x2F;li&gt;
&lt;li&gt;Higher model confidence correlates with increased prompt robustness&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This means that two semantically equivalent prompts can produce dramatically different outputs, making prompt engineering a high stakes optimization problem with no clear gradient signal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-real-traditional-debugging-to-save-me&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-real-traditional-debugging-to-save-me&quot; aria-label=&quot;Anchor link for: no-real-traditional-debugging-to-save-me&quot;&gt;No real traditional debugging to save me&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Traditional software debugging relies on:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deterministic execution&lt;&#x2F;strong&gt; - Same input → same output&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Inspectable state&lt;&#x2F;strong&gt; - Variables, stack traces, breakpoints&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Localized effects&lt;&#x2F;strong&gt; - Changes propagate predictably&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;LLM prompts violate all three assumptions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Outputs are stochastic (using &lt;code&gt;temperature=0&lt;&#x2F;code&gt; gives more stable comparisons)&lt;&#x2F;li&gt;
&lt;li&gt;Internal model state is opaque (billions of parameters, no interpretable variables)&lt;&#x2F;li&gt;
&lt;li&gt;Token interactions are highly non-local (attention spans the entire context)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Perturbation-based saliency addresses this by treating the LLM as a black-box function and inferring input importance from output changes under controlled edits, without requiring model internals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-maths-behind-this&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-maths-behind-this&quot; aria-label=&quot;Anchor link for: the-maths-behind-this&quot;&gt;The Maths behind this&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;10.1145&#x2F;361219.361220&quot;&gt;Vector Space Model (VSM)&lt;&#x2F;a&gt;, represents text as vectors in a high-dimensional space where each dimension corresponds to a distinct term (or in our case, character n-gram). So, the texts with similar content will have similar vector representations, enabling geometric operations (distance, angle) to capture semantic relationships.&lt;&#x2F;p&gt;
&lt;p&gt;The things I am gonna discuss below use character trigrams rather than word-level tokens. A character n-gram is a contiguous sequence of n characters extracted from text. Why? &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aclanthology.org&#x2F;2022.rocling-1.7.pdf&quot;&gt;Character trigram overlap is effective for sentence alignment in text simplification tasks&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Property&lt;&#x2F;th&gt;&lt;th&gt;Benefit&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Language-agnostic&lt;&#x2F;td&gt;&lt;td&gt;Works for any language without tokenizers&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Typo-robust&lt;&#x2F;td&gt;&lt;td&gt;Small character changes don’t destroy similarity&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;No external dependencies&lt;&#x2F;td&gt;&lt;td&gt;No NLP libraries required&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Paraphrase-tolerant&lt;&#x2F;td&gt;&lt;td&gt;Captures subword patterns that survive rephrasing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Computationally efficient&lt;&#x2F;td&gt;&lt;td&gt;O(L) extraction, sparse representation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;We treat Saliency as Divergence. If a phrase is important to the model’s output, removing or altering it should cause the output to change significantly. Obviously!!&lt;&#x2F;p&gt;
&lt;p&gt;More formally, let :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$P = [p_1, p_2, …, p_n]$ be the prompt decomposed into $n$ phrases&lt;&#x2F;li&gt;
&lt;li&gt;$f: \text{Prompt} \rightarrow \text{Output}$ be the LLM function&lt;&#x2F;li&gt;
&lt;li&gt;$P_{-i}$ denote the prompt with phrase $p_i$ perturbed (replaced, removed, or paraphrased)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The saliency score for phrase $p_i$ is:&lt;&#x2F;p&gt;
&lt;p&gt;$$S(p_i) = 1 - \text{sim}(f(P), f(P_{-i}))$$&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Interpretation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;$S(p_i) = 0$: Perturbing $p_i$ causes no change → phrase is redundant&lt;&#x2F;li&gt;
&lt;li&gt;$S(p_i) = 1$: Perturbing $p_i$ causes complete divergence → phrase is critical&lt;&#x2F;li&gt;
&lt;li&gt;$S(p_i) \in (0, 1)$: Partial influence&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This formulation treats saliency as &lt;strong&gt;output divergence under intervention&lt;&#x2F;strong&gt;, a causal notion that measures the counterfactual impact of each phrase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;perturbation-methods&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#perturbation-methods&quot; aria-label=&quot;Anchor link for: perturbation-methods&quot;&gt;Perturbation Methods&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Method&lt;&#x2F;th&gt;&lt;th&gt;What you do&lt;&#x2F;th&gt;&lt;th&gt;API cost&lt;&#x2F;th&gt;&lt;th&gt;When to use&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Perturbation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Replace phrase with &lt;code&gt;[...]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;N+1&lt;&#x2F;td&gt;&lt;td&gt;Default: fast, keeps sentence structure.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Omission&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Remove phrase entirely&lt;&#x2F;td&gt;&lt;td&gt;N+1&lt;&#x2F;td&gt;&lt;td&gt;Short prompts; you want to see effect of full removal.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Paraphrase&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ask an LLM to rewrite the phrase to be vague, then run agent&lt;&#x2F;td&gt;&lt;td&gt;2N+1&lt;&#x2F;td&gt;&lt;td&gt;When you care about semantic content only (slower, more API calls).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;For agentic workflows, perturbation or omission is usually enough; paraphrase is for deeper semantic analysis when needed. The paraphrase method isolates semantic content from structural presence:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Perturbation tests: “What if this phrase were obscured?”&lt;&#x2F;li&gt;
&lt;li&gt;Omission tests: “What if this phrase were absent?”&lt;&#x2F;li&gt;
&lt;li&gt;Paraphrase tests: “What if this phrase said nothing specific?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the most faithful measure of &lt;strong&gt;information contribution&lt;&#x2F;strong&gt; because it controls for the structural role of the phrase while zeroing out its semantic payload.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;when-to-use-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-to-use-it&quot; aria-label=&quot;Anchor link for: when-to-use-it&quot;&gt;When to use it?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Before shipping: audit which instructions and tool descriptions the model really uses.&lt;&#x2F;li&gt;
&lt;li&gt;When debugging: the agent ignores a rule or uses the wrong tool → check if that part of the prompt has low saliency. See which tool descriptions actually affect tool choice.&lt;&#x2F;li&gt;
&lt;li&gt;When trimming: you need a shorter system prompt without losing behaviour → prune by saliency, then re-test.&lt;&#x2F;li&gt;
&lt;li&gt;Adding few-shot examples: System prompt before&#x2F;after adding examples. Check which examples change behaviour; drop ones with near-zero impact.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-this-works&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-this-works&quot; aria-label=&quot;Anchor link for: why-this-works&quot;&gt;Why this works?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Core idea: If a phrase matters, changing or removing it should change the output. If the output barely changes, that phrase is not pulling much weight. So we &lt;strong&gt;perturb one phrase at a time&lt;&#x2F;strong&gt; and measure &lt;strong&gt;how much the output changes&lt;&#x2F;strong&gt; (e.g. with a similarity score). That change is the phrase’s “importance” for that run.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Marginal contribution: This is the same idea as “leave-one-out” importance in interpretability: you’re measuring the marginal contribution of each phrase to the outcome. It’s a simple approximation to more formal notions (e.g. Shapley-like attribution) that would average over many subsets; here we only compare “full prompt” vs “without this phrase” (or “with this phrase masked”), which is cheap and usually enough for prompt tuning.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Comparing outputs: We need a single number for “how different is output A from output B?” Character-trigram cosine similarity is &lt;strong&gt;language-agnostic&lt;&#x2F;strong&gt;, has no extra dependencies, and is robust to small wording changes. So: turn both outputs into trigram frequency vectors, compute cosine similarity, then use &lt;strong&gt;1 − similarity&lt;&#x2F;strong&gt; as divergence (saliency). For higher semantic fidelity you can swap in embedding-based similarity later (e.g. Sentence-BERT); the workflow stays the same.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Why phrases, not tokens: Phrase-level (sentence&#x2F;clause chunks) gives a good balance: token-level is noisy and expensive; whole-prompt is too coarse. So we split the prompt into phrases, perturb one phrase at a time, and attribute importance to the phrase.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;implementation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#implementation&quot; aria-label=&quot;Anchor link for: implementation&quot;&gt;Implementation&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Assume your agent as a black box: (system_prompt, user_message) → output. Wrap your agent in one async function that takes &lt;code&gt;(system_prompt, user_message)&lt;&#x2F;code&gt; and returns a string (or a metric).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What to return: The full response text. If your agent uses tools, concatenate the tool calls and final answer into one string. If you care specifically about tool choice, return just the tool names&#x2F;args.&lt;&#x2F;li&gt;
&lt;li&gt;Temperature: Set to 0 for reproducibility. Even then, outputs can drift slightly due to batching&#x2F;caching—handle this with multiple runs (see below). I should think about this a bit more, will update this point later.&lt;&#x2F;li&gt;
&lt;li&gt;Framework doesn’t matter. LangChain, OpenAI, Anthropic, custom—just wrap it so it takes two strings and returns one string.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tokenize-the-prompt-into-phrases&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tokenize-the-prompt-into-phrases&quot; aria-label=&quot;Anchor link for: tokenize-the-prompt-into-phrases&quot;&gt;Tokenize the Prompt into Phrases&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Split the system prompt into chunks you’ll perturb one at a time.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Split at sentence boundaries (&lt;code&gt;.&lt;&#x2F;code&gt; &lt;code&gt;!&lt;&#x2F;code&gt; &lt;code&gt;?&lt;&#x2F;code&gt; newline).&lt;&#x2F;li&gt;
&lt;li&gt;If a sentence is longer than ~60 characters, sub-split at commas&#x2F;semicolons.&lt;&#x2F;li&gt;
&lt;li&gt;Accumulate sub-chunks until each is at least ~35 characters.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Why phrase-level?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Token-level is too noisy (one token rarely matters alone) and expensive (many API calls).&lt;&#x2F;li&gt;
&lt;li&gt;Whole-prompt is too coarse (no granularity).&lt;&#x2F;li&gt;
&lt;li&gt;Phrase-level (35–60 chars) balances signal and cost.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For structured prompts (JSON schemas, code blocks), consider custom tokenizers that respect structure boundaries.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;get-the-baseline-output&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#get-the-baseline-output&quot; aria-label=&quot;Anchor link for: get-the-baseline-output&quot;&gt;Get the Baseline Output&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Run your agent with the full, unmodified system prompt and a representative user message. Save this output, it’s your reference for comparison.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;perturb-each-phrase-and-measure-divergence&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#perturb-each-phrase-and-measure-divergence&quot; aria-label=&quot;Anchor link for: perturb-each-phrase-and-measure-divergence&quot;&gt;Perturb Each Phrase and Measure Divergence&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;For each phrase &lt;code&gt;i&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Perturb:&lt;&#x2F;strong&gt; Replace phrase &lt;code&gt;i&lt;&#x2F;code&gt; with &lt;code&gt;[...]&lt;&#x2F;code&gt; (or remove it entirely for omission method).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Run:&lt;&#x2F;strong&gt; Call your agent with the perturbed prompt and the same user message.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compare:&lt;&#x2F;strong&gt; Measure how different the new output is from the baseline.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Score:&lt;&#x2F;strong&gt; &lt;code&gt;saliency = 1 - similarity(baseline, perturbed_output)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;High saliency = perturbing this phrase changed the output a lot = important phrase.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;choose-a-similarity-function&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#choose-a-similarity-function&quot; aria-label=&quot;Anchor link for: choose-a-similarity-function&quot;&gt;Choose a Similarity Function&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You need a single number for “how similar are these two outputs?”&lt;&#x2F;p&gt;
&lt;p&gt;I prefer using Sentence embeddings :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Use a model like Sentence-BERT (&lt;code&gt;all-MiniLM-L6-v2&lt;&#x2F;code&gt; is fast and good).&lt;&#x2F;li&gt;
&lt;li&gt;Encode both outputs to vectors, compute cosine similarity.&lt;&#x2F;li&gt;
&lt;li&gt;Captures semantic equivalence: paraphrases score high.&lt;&#x2F;li&gt;
&lt;li&gt;Requires &lt;code&gt;sentence-transformers&lt;&#x2F;code&gt; library or an embedding API.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;normalise-scores&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#normalise-scores&quot; aria-label=&quot;Anchor link for: normalise-scores&quot;&gt;Normalise Scores&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Raw saliency scores depend on the specific outputs and similarity function. To compare across phrases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Min-max normalise to [0, 1]: &lt;code&gt;(score - min) &#x2F; (max - min)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Now 1.0 = most important phrase in this prompt; 0.0 = least important.&lt;&#x2F;li&gt;
&lt;li&gt;If all scores are equal, return 0.5 for all (no differentiation).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;batch-over-multiple-user-messages&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#batch-over-multiple-user-messages&quot; aria-label=&quot;Anchor link for: batch-over-multiple-user-messages&quot;&gt;Batch Over Multiple User Messages&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Saliency for one user message tells you “importance for this query.” To generalize:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Pick 5–10 representative user messages (cover different intents your agent handles).&lt;&#x2F;li&gt;
&lt;li&gt;Run saliency for each user message.&lt;&#x2F;li&gt;
&lt;li&gt;Average the normalised scores per phrase across all user messages.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Now you know which phrases matter on average, not just for one query.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multiple-runs-for-stability&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiple-runs-for-stability&quot; aria-label=&quot;Anchor link for: multiple-runs-for-stability&quot;&gt;Multiple Runs for Stability&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Even with &lt;code&gt;temperature=0&lt;&#x2F;code&gt;, outputs can vary slightly. For production:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Run each perturbation K times&lt;&#x2F;li&gt;
&lt;li&gt;Average the scores across runs.&lt;&#x2F;li&gt;
&lt;li&gt;Compute 95% confidence intervals: &lt;code&gt;mean ± 1.96 * (stdev &#x2F; sqrt(K))&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Pruning rule:&lt;&#x2F;strong&gt; Only drop phrases where the &lt;strong&gt;upper bound&lt;&#x2F;strong&gt; of the CI is below your threshold (e.g. &amp;lt; 0.3). This ensures you’re confident the phrase is low-impact, not just noisy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;act-on-the-results&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#act-on-the-results&quot; aria-label=&quot;Anchor link for: act-on-the-results&quot;&gt;Act on the Results&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Score range&lt;&#x2F;th&gt;&lt;th&gt;Interpretation&lt;&#x2F;th&gt;&lt;th&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;High (top third)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Critical phrases&lt;&#x2F;td&gt;&lt;td&gt;Protect; clarify if agent misbehaves&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Low (bottom third, CI upper &amp;lt; 0.3)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Redundant or weak&lt;&#x2F;td&gt;&lt;td&gt;Candidate for pruning&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Middle&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Moderate impact&lt;&#x2F;td&gt;&lt;td&gt;Keep; revisit later&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Pruning workflow:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Drop low-saliency phrases (where upper CI &amp;lt; threshold).&lt;&#x2F;li&gt;
&lt;li&gt;Re-run your agent on the same and new user messages.&lt;&#x2F;li&gt;
&lt;li&gt;Verify behaviour is unchanged (use your existing evals).&lt;&#x2F;li&gt;
&lt;li&gt;Iterate.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;detect-interactions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#detect-interactions&quot; aria-label=&quot;Anchor link for: detect-interactions&quot;&gt;Detect Interactions&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Single-phrase saliency assumes independence. To catch conflicts or synergies:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Perturb &lt;strong&gt;pairs&lt;&#x2F;strong&gt; of phrases together.&lt;&#x2F;li&gt;
&lt;li&gt;Compute: &lt;code&gt;interaction(i, j) = saliency(i+j) - saliency(i) - saliency(j)&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Positive = synergy (removing both hurts more than sum). Negative = conflict (removing both hurts less).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Cost is O(N²), so only do this for short prompts or after pruning.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;limitations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#limitations&quot; aria-label=&quot;Anchor link for: limitations&quot;&gt;Limitations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Interactions:&lt;&#x2F;strong&gt; Assumes phrases contribute independently. Conflicting instructions (“Be concise” + “Explain in detail”) can make individual scores misleading. Inspect high- and low-saliency phrases together before pruning.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Embedding cost:&lt;&#x2F;strong&gt; Sentence-BERT adds ~50ms per comparison. For very long outputs, chunk and average.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Phrase boundaries:&lt;&#x2F;strong&gt; Heuristic (sentence&#x2F;clause). Domain-specific prompts (code, JSON schemas) may need custom tokenizers.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;API cost:&lt;&#x2F;strong&gt; N+1 calls per user message per run. Keep N small by pre-pruning or using fewer user messages.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;edit&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#edit&quot; aria-label=&quot;Anchor link for: edit&quot;&gt;Edit&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Actually did &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harsh-ps-2003&#x2F;rapt&quot;&gt;the implementation&lt;&#x2F;a&gt; today! It’s a bit advanced implementation. It’s CLI based for now, maybe should make it browser based if want to post about it?&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The chronicles of training FBPINNs</title>
          <pubDate>Fri, 02 Jan 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/the-chronicles-of-training-fbpinns/</link>
          <guid>https://harsh-ps-2003.github.io/writes/the-chronicles-of-training-fbpinns/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/the-chronicles-of-training-fbpinns/">&lt;p&gt;Right now I am training FBPINNs on a supercomputer. yay!. This distributed training is a total headache, so this is a writeup about how I see am optimizing the resources I have been bestowed upon. I wanna have some bitter sweet memories of GPUs when I graduate ;)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;basics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#basics&quot; aria-label=&quot;Anchor link for: basics&quot;&gt;Basics&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;First and foremost, I am using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;images.nvidia.com&#x2F;content&#x2F;volta-architecture&#x2F;pdf&#x2F;volta-architecture-whitepaper.pdf&quot;&gt;V100&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The V100 is built from multiple Streaming Multiprocessors (SMs), each executing warps (block of 32 threads) via CUDA cores (the general‑purpose ALUs that execute most integer and BF16 operations) and one instruction issued by the warp scheduler is carried out simultaneously by all active CUDA cores for that warp (SIMT style). in a SIMT fashion (Single Instruction Multiple Threads), backed by register files, small L1&#x2F;texture caches, and shared memory. There are Tenor cores for specialized matrix‑multiply‑accumulate operations. Instead of doing scalar FMA, a single tensor‑core instruction multiplies small matrices (e.g., 16×16 tiles) in mixed precision (FP16&#x2F;BF16&#x2F;TF32 → FP32&#x2F;FP16 accumulators). They sit alongside CUDA cores and are used when your kernel uses tensor&#x2F;matrix instructions (e.g., GEMM, convolutions).&lt;&#x2F;p&gt;
&lt;p&gt;All SMs talk to a large on‑package HBM2 memory stack through several memory controllers, providing around 900 GB&#x2F;s of memory bandwidth for local tensor data (activations, parameters, wavefields, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;CPU and GPU communicate over the PCI Express bus (it’s not technically a bus but a point to point connection). From the perspective of software running on the CPU, these days, that communication is typically in the form of memory-mapped IO. The GPU has registers and memory mapped into the CPU address space using PCIe. A write to a particular address generates a message on the PCIe bus that’s received by the GPU and produces a write to a GPU register or GPU memory. The GPU also has access to system memory through the PCIe bus. Typically, the CPU will construct buffers in memory with data (textures, vertices), commands, and GPU code. It will then store the buffer address in a GPU register and ring some sort of “doorbell” by writing to another GPU register. The GPU (specifically, the GPU command processor) will then read the buffers from system memory, and start executing the commands. Those commands can include, for example, loading GPU shader programs into shader memory and triggering the shaders to execute those shaders.&lt;&#x2F;p&gt;
&lt;p&gt;There is an on‑chip L2 cache shared across SMs that backs global memory accesses and also serves as the interface to off‑chip links like NVLink and PCIe.&lt;&#x2F;p&gt;
&lt;p&gt;Each V100 has high‑bandwidth HBM2 on‑package, giving around 900 GB&#x2F;s of local memory bandwidth, so local tensor math is extremely fast compared to any inter‑GPU link. Each V100 is also connected to the host via PCIe (x16 slot), which has much lower bandwidth and higher latency than NVLink. Each V100 supports up to 6 NVLink 2.0 links, at about 50 GB&#x2F;s bidirectional per link, for an aggregate of up to 300 GB&#x2F;s GPU‑to‑GPU bandwidth per device. This is an order of magnitude faster and lower‑latency than going GPU → CPU over PCIe and then to another GPU, so if two GPUs must frequently exchange activations, parameters, or halo regions, I would want that traffic to run over NVLink, not PCIe.&lt;&#x2F;p&gt;
&lt;p&gt;The CPU has DRAM and possibly a NIC (InfiniBand&#x2F;Ethernet) for off‑node traffic. Any data that must leave the node (checkpoints, distributed training gradients over nodes) typically travels GPU → PCIe → CPU memory → NIC → network. In reverse, GPU results (e.g., metrics, checkpoints) go back GPU HBM2 → L2 → PCIe → CPU DRAM.&lt;&#x2F;p&gt;
&lt;p&gt;At the hardware level, NVLink attaches logically near the GPU’s L2&#x2F;memory controller region, so a tensor in GPU0’s HBM2 can be read&#x2F;written by GPU1 over NVLink without going through the CPU or system DRAM. So, the hardware path is: SMs on GPU0 write halo tensors to HBM2 → L2 → NVLink serdes → L2&#x2F;HBM2 on GPU1, and vice versa.&lt;&#x2F;p&gt;
&lt;p&gt;How it all works together :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The CPU (host) calls something like cudaMalloc to reserve buffers in device (GPU) memory. The host uses an async version to DMA data over PCIe or NVLink into those device buffers. Using pinned (page‑locked) host memory allows faster transfers because the driver can DMA directly from those pages without an extra staging copy.&lt;&#x2F;li&gt;
&lt;li&gt;The host call submits a grid of thread blocks to the GPU, and the CPU continues immediately (kernels are asynchronous). The GPU’s work distributor assigns each thread block to a SM when that SM has enough registers, shared memory, and slots for warps. On each SM, blocks are decomposed into warps (typically 32 threads). Warp schedulers on the SM issue instructions from ready warps each cycle. Modern SMs have multiple warp schedulers; each cycle they choose ready warps and issue instructions to CUDA cores, tensor cores, and load&#x2F;store units.&lt;&#x2F;li&gt;
&lt;li&gt;Those instructions run on CUDA cores or tensor cores, using registers and shared memory, while load&#x2F;store units handle memory traffic.&lt;&#x2F;li&gt;
&lt;li&gt;When a warp stalls (e.g., waiting on DRAM), the SM instantly switches to another ready warp, hiding latency and keeping the execution units busy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, an SM is essentially a many‑lane vector processor with its own control (warp schedulers) and fast memories, where CUDA cores handle general math, tensor cores accelerate matrix math, and the control logic juggles thousands of threads to maximize utilization.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tech-stack&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-tech-stack&quot; aria-label=&quot;Anchor link for: the-tech-stack&quot;&gt;The Tech Stack&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are layers to this circus man! OSI model on steroid :&lt;&#x2F;p&gt;
&lt;h3 id=&quot;orchestration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#orchestration&quot; aria-label=&quot;Anchor link for: orchestration&quot;&gt;Orchestration&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;SLURM is the job scheduler I use to allocate GPUs and manage queue fairness. Unlike interactive execution, batch jobs with SLURM guarantee reproducible resource allocation, critical for performance benchmarking.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;drivers-and-libraries&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#drivers-and-libraries&quot; aria-label=&quot;Anchor link for: drivers-and-libraries&quot;&gt;Drivers and LIbraries&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;CUDA 12.9 provides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GPU kernel execution runtime: Compiles and executes compute kernels on V100s (JAX’s XLA compiler generates CUDA kernels optimized for V100 Tensor Cores, more on that later)&lt;&#x2F;li&gt;
&lt;li&gt;cuDNN (CUDA Deep Neural Network Library): Optimized convolution and activation kernels&lt;&#x2F;li&gt;
&lt;li&gt;cuBLAS: GPU matrix multiplication (used implicitly by neural network layers) - for handling forward and backward passes in case of PINNs&lt;&#x2F;li&gt;
&lt;li&gt;cuSolver: GPU linear algebra solver&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;ai-runtime&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-runtime&quot; aria-label=&quot;Anchor link for: ai-runtime&quot;&gt;AI Runtime&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;JAX is the computational framework. Under the hood:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;JAX: High-level API for autodiff and functional transformations. I mark training&#x2F;inference loops with JIT to get compiled functions.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;XLA (Accelerated Linear Algebra)&lt;&#x2F;strong&gt;: LLVM-based compiler that converts JAX code to CUDA kernels. XLA traces the function, builds an HLO graph. It fuses operations where possible (e.g., elementwise stencils + activation functions) and maps them to GPU operations (call cuBLAS&#x2F;cuDNN kernels, or emit custom fused kernels).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those GPU operations correspond to CUDA kernels with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Grid and block dimensions (how many thread blocks, threads per block).&lt;&#x2F;li&gt;
&lt;li&gt;Arguments (pointers to tensors in HBM2, scalars, etc.).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;They are enqueued into CUDA streams (a queue of operations like kernels, memcpys, events, etc that execute in order on a GPU, different streams can run concurrently if there are resources). Once a kernel is launched on a stream:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The GPU’s command processor pulls it from the queue.&lt;&#x2F;li&gt;
&lt;li&gt;It sets up the grid of thread blocks and schedules them onto SMs.&lt;&#x2F;li&gt;
&lt;li&gt;Each SM instantiates multiple warps (32 threads each), uses the warp scheduler to interleave warps and hide memory latency and issues memory loads&#x2F;stores to global HBM2 via L1&#x2F;L2, and uses the NVLink&#x2F;PCIe fabric only when accessing peer memory.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The streams ensure the right order (e.g., do not consume halo before copy is done), and graphs allow that whole arrangement to be replayed efficiently.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;networking&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#networking&quot; aria-label=&quot;Anchor link for: networking&quot;&gt;Networking&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_P2P_DISABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;           #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Enable GPU-to-GPU P2P&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_IB_DISABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; InfiniBand disabled (not used)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_MIN_NCHANNELS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 32 parallel channels&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_BUFFSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;8388608&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 8MB buffers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.nvidia.com&#x2F;blog&#x2F;understanding-nccl-tuning-to-accelerate-gpu-to-gpu-communication&#x2F;&quot;&gt;NCCL handles GPU-to-GPU communication&lt;&#x2F;a&gt; across NVLink. I used:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NVLink bandwidth&lt;&#x2F;strong&gt;: ~300 GB&#x2F;s between the two V100s&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Collective operations&lt;&#x2F;strong&gt;: &lt;code&gt;all-reduce&lt;&#x2F;code&gt;, &lt;code&gt;broadcast&lt;&#x2F;code&gt;, &lt;code&gt;reduce-scatter&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For FBPINNs, this enables:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Multi-GPU subdomain parallelism (each GPU owns different subdomains)&lt;&#x2F;li&gt;
&lt;li&gt;Synchronization via hardware &lt;code&gt;all-reduce&lt;&#x2F;code&gt; for combining weighted sums&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;cpu-optimizaton&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cpu-optimizaton&quot; aria-label=&quot;Anchor link for: cpu-optimizaton&quot;&gt;CPU Optimizaton&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Modern scientific libraries (NumPy, BLAS, OpenBLAS, MKL, etc.) use OpenMP‑style threading to parallelize CPU operations like matrix–matrix multiplications, solvers, FFTs, and so on. When allowed to use many threads, they can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jax-ml&#x2F;jax&#x2F;issues&#x2F;743&quot;&gt;Launch as many threads as CPU cores&#x2F;HT threads (e.g., 16–64 threads) for a single BLAS call&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jax-ml&#x2F;jax&#x2F;issues&#x2F;5022&quot;&gt;Quickly saturate CPU cores, generating high CPU usage and memory‑bandwidth pressure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After JAX offloads GPU work, the CPU is still responsible for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Data loading, batching, and small preprocessing&lt;&#x2F;li&gt;
&lt;li&gt;Logging and profiling&lt;&#x2F;li&gt;
&lt;li&gt;A few tiny BLAS‑like operations (often 1–2 ms per step)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If each of these tiny BLAS calls spawns many threads, things happens:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CPU threads compete with JAX’s runtime and GPU driver threads for OS scheduling, delaying kernel launches and GPU context switches by tens to hundreds of microseconds.&lt;&#x2F;li&gt;
&lt;li&gt;Many active threads trample L1&#x2F;L2&#x2F;L3 caches and saturate memory bandwidth, which can indirectly slow down GPU transfers (since PCIe traffic often shares the same memory subsystem and CPU memory bus).&lt;&#x2F;li&gt;
&lt;li&gt;The result is increased step‑time variance and reduced GPU duty cycle, even though the GPU kernel itself is unchanged !!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In my FBPINN setup, the GPU is dominated by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Thousands of small PDE kernels&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;research.colfax-intl.com&#x2F;wp-content&#x2F;uploads&#x2F;2023&#x2F;12&#x2F;colfax-gemm-kernels-hopper.pdf&quot;&gt;Dense matmuls&lt;&#x2F;a&gt; and autograd kernels, so step times are often 20–100 ms; tiny CPU jitters do add up over thousands of steps&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By carefully limiting BLAS&#x2F;OpenMP threading, I keep the CPU mostly idle and give JAX&#x2F;GPU‑driver threads clean access to CPU time and cache&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Force BLAS&#x2F;NumPy to single‑threaded mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;OMP_NUM_THREADS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;OPENBLAS_NUM_THREADS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;MKL_NUM_THREADS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;VECLIB_MAXIMUM_THREADS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NUMEXPR_NUM_THREADS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; For JAX itself, I also restrict XLA&amp;#39;s internal threadpool:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;os.environ[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;XLA_FLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;--xla_cpu_multi_thread_eigen=false &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;intra_op_parallelism_threads=1 &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;inter_op_parallelism_threads=1&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my high‑throughput training, this setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Reduced CPU overhead from ~1–2 ms to ~0.2–0.5 ms per step.&lt;&#x2F;li&gt;
&lt;li&gt;And improved GPU duty cycle by 5–10% and reduce step‑time variance by 20–40%.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I did this because I have a GPU-bound workload, but if it would have been CPU‑bound workloads (heavy data loading, preprocessing, small models, etc), I would have used multiple threads (e.g., OMP_NUM_THREADS=4–8) and profile where time is spent, and then tune thread count and CPU pinning accordingly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jax-cpu-threading-and-parallelism&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#jax-cpu-threading-and-parallelism&quot; aria-label=&quot;Anchor link for: jax-cpu-threading-and-parallelism&quot;&gt;JAX CPU threading and parallelism&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bnikolic.co.uk&#x2F;blog&#x2F;python&#x2F;jax&#x2F;2023&#x2F;03&#x2F;22&#x2F;jax-multithreaded.html&quot;&gt;JAX’s CPU backend does provide intra‑op parallelism for some operations&lt;&#x2F;a&gt; (e.g., many BLAS&#x2F;LAPACK‑like matrix operations use Eigen’s internal threadpool). However not all operations are multithreaded. for example, FFT operations on CPU historically did not use multi‑threading, and even in newer versions you may still see limited parallelism compared with hand‑tuned BLAS‑based FFTs. JAX does not provide general inter‑op parallelism: it won’t automatically schedule multiple independent operations to run in parallel across CPU cores. Because of this, JAX’s CPU backend is not optimized for maximum CPU utilization in the HPC sense. It prioritizes correctness and portability as well as integration with XLA and GPU&#x2F;TPU targets
rather than squeezing every FLOP out of a large CPU node.&lt;&#x2F;p&gt;
&lt;p&gt;This means that, for many CPU‑heavy workloads, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.orgdoifullHtml&#x2F;10.1145&#x2F;3624062.3624186&#x2F;&quot;&gt;JAX can be slower than single‑core C++ and significantly slower than well‑optimized parallel C++&#x2F;Fortran&#x2F;MPI code. In practice, JAX is best treated as a convenient, compiler‑enhanced numerical stack rather than a drop‑in HPC‑optimized CPU backend&lt;&#x2F;a&gt;. JAX’s JIT compiler can be very fast in many applications, but finely‑tuned C++ can be much faster for certain problems. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dfm.io&#x2F;posts&#x2F;extending-jax&#x2F;&quot;&gt;You can extend JAX&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;topology-aware-sharding&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#topology-aware-sharding&quot; aria-label=&quot;Anchor link for: topology-aware-sharding&quot;&gt;Topology-aware Sharding&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Yay! A fancy word to throw around!!!&lt;&#x2F;p&gt;
&lt;p&gt;At a high level &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.systemoverflow.com&#x2F;learn&#x2F;ml-training-infrastructure&#x2F;distributed-training&#x2F;3d-parallelism-and-topology-aware-mapping-in-production&quot;&gt;topology‑aware sharding&lt;&#x2F;a&gt; means I place model shards on GPUs in a way that matches the communication pattern of my algorithm to the physical GPU interconnect (here, NVLink between the two V100s) so that the most chatty peers talk over the fastest links, minimizing PCIe or host‑network hops.&lt;&#x2F;p&gt;
&lt;p&gt;If I ignore hardware topology and just say “I have N GPUs, shard the model arbitrarily”, the runtime might place logically adjacent model pieces on GPUs that are far apart in the physical network (e.g., across nodes or over pure PCIe). This increases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Latency for every cross‑shard communication.&lt;&#x2F;li&gt;
&lt;li&gt;Contention on shared links (PCIe root complex, host NIC).&lt;&#x2F;li&gt;
&lt;li&gt;Synchronization overhead, because each step waits on slower communication.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I clearly dont want this cuz I am smart ;)
I first understand the graph of GPU interconnects (which GPUs have NVLink, which are only PCIe peers, which are across Infiniband), and then map logical communication groups (tensor‑parallel group, pipeline stage boundaries, domain‑decomposition neighbors) onto the fastest‑connected subset.&lt;&#x2F;p&gt;
&lt;p&gt;The principle is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;High‑frequency, latency‑sensitive collectives (e.g., &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;docs&#x2F;transformers&#x2F;en&#x2F;perf_infer_gpu_multi&quot;&gt;tensor parallel&lt;&#x2F;a&gt; all‑reduces, halo exchanges every iteration) stay on strongest links like NVLink.&lt;&#x2F;li&gt;
&lt;li&gt;Medium‑frequency transfers (e.g., pipeline activations, subdomain checkpoint exchange) can tolerate one slower hop.&lt;&#x2F;li&gt;
&lt;li&gt;Low‑frequency work (e.g., global gradient all‑reduce, checkpointing) can spill over slower interconnects like Ethernet&#x2F;IB.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But how to verify topology of nodes? I used&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nvidia-smi topo -m&lt;&#x2F;code&gt; to see the connectivity matrix; NVLink‑connected GPUs show as NV1&#x2F;NV2&#x2F;…, PCIe only as PHB or similar&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;nvidia-smi -q -d NVLINK&lt;&#x2F;code&gt; to check which NVLink links are up between the two V100s&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;nvidia-smi -L&lt;&#x2F;code&gt; or &lt;code&gt;CUDA_VISIBLE_DEVICES&lt;&#x2F;code&gt; to confirm device indices and then map shard placement: e.g., keep the most chatty tensor&#x2F;model‑parallel ranks on GPU0 and GPU1 of the same node&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Once you know which GPU indices share NVLink, you can implement topology‑aware sharding at the framework level (PyTorch device_ids &#x2F; process group mapping, JAX mesh layout, DeepSpeed&#x2F;DTensor placement) so that heavy all‑reduce&#x2F;all‑to‑all happens within those NVLink pairs and only coarser‑grained sync crosses nodes over InfiniBand.&lt;&#x2F;p&gt;
&lt;p&gt;Enough hardware, how did I use this information? In the FBPINN subsurface modeling, I had a large 2D domain decomposed into lots of subdomains with partition‑of‑unity windows. Each subdomain corresponds to a small local network, but neighboring subdomains still need to exchange information (e.g., wavefield values near the overlap, gradients for the inversion) each iteration, which creates a neighbor communication pattern reminiscent of a 2D stencil.&lt;&#x2F;p&gt;
&lt;p&gt;Which subdomain goes to same GPU? I grouped subdomains so that those with the heaviest cross‑coupling (e.g., central, high‑wave‑energy regions) reside on the same GPU, so their communication is purely local HBM2 traffic, which is cheapest.  Less tightly coupled or boundary subdomains (small number of cross‑boundary subdomains) could be split across GPUs, with their overlapped halo data sent over NVLink each step. I designed the field exchange as batched halo exchanges. Instead of many small transfers, I pack halo tensors belonging to adjacent subdomains into contiguous buffers and send them over NVLink in fewer, larger transfers, making better use of the ~300 GB&#x2F;s aggregate bandwidth. There is no reason for halo data to go to CPU DRAM or across the NIC on each iteration, that would be orders of magnitude slower and would stall the SMs waiting on PCIe round‑trips.&lt;&#x2F;p&gt;
&lt;p&gt;In JAX terms, this was effectively a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2403.03699v1&quot;&gt;model‑parallel sharding on distributed infrastructure&lt;&#x2F;a&gt;. The global domain is the model, and each subdomain network is a shard.&lt;&#x2F;p&gt;
&lt;p&gt;So, how it works under the hood? Let me walk through one FBPINN training step in this topology‑aware setup in simplistic way (just 2 GPUs):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Before training, I decide: “these 40 subdomains on GPU0, these 35 on GPU1.” I also precompute neighbor lists and overlap regions so I know exactly which data each GPU must send&#x2F;receive at each step.&lt;&#x2F;li&gt;
&lt;li&gt;On each V100, the bulk of compute (forward PDE solve and local backward) runs purely on local HBM2, maximizing the ~900 GB&#x2F;s bandwidth and SM utilization; no inter‑GPU traffic yet. This is where JAX JIT helps; it compiles each subdomain’s work into efficient fused kernels and schedules them over the SMs.&lt;&#x2F;li&gt;
&lt;li&gt;For subdomains at the boundary between GPU0 and GPU1, I gather the boundary tensors (wavefields on the overlap, maybe derivative info) into contiguous buffers. I then initiate device‑to‑device copies or NCCL sends&#x2F;receives across the NVLink link, which runs at up to 300 GB&#x2F;s aggregate and significantly lower latency than PCIe. Because the GPUs are directly NVLink‑connected, the driver routes these as peer‑to‑peer transfers without staging through host memory.&lt;&#x2F;li&gt;
&lt;li&gt;After the halo exchange, I perform block‑level accumulation steps (e.g., summing overlapping contributions, enforcing partition‑of‑unity consistency) and then proceed to the next time step or optimization step.​ I explicitly synchronize only where necessary (e.g., before using updated halos) to avoid global barriers that would stall both GPUs.&lt;&#x2F;li&gt;
&lt;li&gt;The same idea extends to more complex topologies: you place the most communication‑heavy neighbors in groups that sit on NVLink or NVSwitch within a node, and only lower‑frequency communications (e.g., checkpoints, global misfit evaluation) cross node boundaries over InfiniBand or Ethernet.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The benefits of topology‑aware sharing is clear :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Higher effective throughput: by matching communication patterns to the fastest links, you utilize the ~300 GB&#x2F;s NVLink bandwidth and avoid PCIe bottlenecks.&lt;&#x2F;li&gt;
&lt;li&gt;Lower latency and less idle time: GPUs spend more time doing local HBM2 math and less time waiting for halo or activation data.&lt;&#x2F;li&gt;
&lt;li&gt;Better scalability: as you move toward multi‑node, the same principles generalize to NVSwitch vs InfiniBand vs Ethernet, which is exactly the sort of reasoning you need in a hyperscaler‑grade AI cluster.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But the tradeoffs are real :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;More complex placement logic: you must know your communication graph and your hardware topology, and implement placement heuristics or algorithms.&lt;&#x2F;li&gt;
&lt;li&gt;Reduced flexibility: if you tie your model layout too tightly to a specific topology (e.g., dual‑V100 with certain NVLink layout), porting to a different cluster topology may require changing the sharding plan.&lt;&#x2F;li&gt;
&lt;li&gt;Potential imbalance: minimizing cross‑GPU communication might conflict with load balancing; you sometimes have to trade slightly more communication for better compute balance across GPUs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;gpu-optimizations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#gpu-optimizations&quot; aria-label=&quot;Anchor link for: gpu-optimizations&quot;&gt;GPU optimizations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Well, a lot of them actually.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cuda-graphs-kernel-launch-overhead&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cuda-graphs-kernel-launch-overhead&quot; aria-label=&quot;Anchor link for: cuda-graphs-kernel-launch-overhead&quot;&gt;CUDA Graphs (Kernel Launch Overhead)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Every CUDA kernel launch has ~10-50 microseconds of overhead. My FBPINN training loop runs thousands of PDE evaluations per step, each requiring multiple kernels. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;27038162&#x2F;how-bad-is-it-to-launch-many-small-kernels-in-cuda&quot;&gt;This is a problem!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So, I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2501.09398v1&quot;&gt;CUDA Graphs&lt;&#x2F;a&gt; to tackle this. How it work:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;In the first pass, JAX records a sequence of CUDA kernels into a graph. It runs the full forward + PDE evaluation + backward once, while recording which CUDA kernels are launched, in what order, and with what arguments. This graph is a static description of the GPU workload (a DAG of kernels, memcpys, events, etc.).&lt;&#x2F;li&gt;
&lt;li&gt;Instead of launching 500 kernels one by one from the CPU, the runtime submits the entire pre‑recorded graph to the GPU in a single call. The GPU then orchestrates the 500 kernels internally, with minimal CPU involvement. On modern GPUs, the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.nvidia.com&#x2F;blog&#x2F;constant-time-launch-for-straight-line-cuda-graphs-and-other-performance-enhancements&#x2F;&quot;&gt;repeat launch overhead&lt;&#x2F;a&gt; is roughly constant and small (e.g., 1–3 μs total for the whole graph), regardless of how many kernels are inside it. So subsequent passes replay the graph with 1-2 μs overhead instead of 10-50 μs per kernel.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, a training step with 500 kernels normally costs 500 × 25 μs = 12.5 ms overhead. With graphs 1 graph replay = 2 μs overhead. So, ~30-50% speedup for compute-bound workloads. Yay!! Easy&lt;&#x2F;p&gt;
&lt;p&gt;And it works really well for FBPINNs! Due to fixed batch sizes we have static shapes and thus graphs can be captured (computational pattern is very repetitive, fixed batch sizes, fixed PDE domains, etc.). The structure is almost the same every iteration, only tensor values change. And due to thousands of iterations, overhead savings compound significantly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xla-compiler-flags-v100-specific&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#xla-compiler-flags-v100-specific&quot; aria-label=&quot;Anchor link for: xla-compiler-flags-v100-specific&quot;&gt;XLA Compiler Flags (V100-Specific)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kolonist26-jax-kr.readthedocs.io&#x2F;en&#x2F;latest&#x2F;gpu_performance_tips.html&quot;&gt;XLA performance flags&lt;&#x2F;a&gt; are very much version dependent. Use these with caution. Some flags (like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jax-ml&#x2F;jax&#x2F;issues&#x2F;20763&quot;&gt;latency‑hiding scheduler&lt;&#x2F;a&gt;) can increase memory usage a lot on some models!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; XLA_FLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--xla_gpu_enablefast_min_max &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                  --xla_gpu_enable_triton_gemm &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                  --xla_gpu_enable_latency_hiding_scheduler=true &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                  --xla_gpu_all_reduce_combine_threshold_bytes=134217728 &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;                  --xla_gpu_enable_highest_priority_async_stream=true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Flag breakdown&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--xla_gpu_enable_fast_min_max&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: Use faster, slightly lower-precision min&#x2F;max&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Benefit: 10% faster activation functions (ReLU, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;Tradeoff: Negligible precision loss for PINN training&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--xla_gpu_enable_triton_gemm&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: Replace cuBLAS GEMM with Triton-compiled kernels&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Benefit: 15-25% speedup on matrix multiplication&lt;&#x2F;li&gt;
&lt;li&gt;Triton is an open-source language for writing GPU kernels; auto-tuned for V100&lt;&#x2F;li&gt;
&lt;li&gt;Particularly effective for non-standard matrix shapes (pretty common in FBPINNs)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--xla_gpu_enable_latency_hiding_scheduler&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: Overlap memory operations with compute&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Before: GPU stalls waiting for memory&lt;&#x2F;li&gt;
&lt;li&gt;After: While GPU transfers data, it computes other operations in parallel&lt;&#x2F;li&gt;
&lt;li&gt;Benefit: 10-15% speedup for memory-intensive workloads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--xla_gpu_all_reduce_combine_threshold_bytes=134217728&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: Combine small all-reduce calls&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;128 MB threshold means small reductions are batched into one large reduction&lt;&#x2F;li&gt;
&lt;li&gt;Benefit: ~20-30% faster multi-GPU synchronization&lt;&#x2F;li&gt;
&lt;li&gt;Why: Fewer NCCL calls so better utilization of NVLink&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;--xla_gpu_enable_highest_priority_async_stream&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: Prioritize compute stream&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Benefit: Compute kernels run faster by preempting lower-priority streams&lt;&#x2F;li&gt;
&lt;li&gt;Minor effect on single-GPU, significant on multi-GPU&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I estimate a combined improvement of ~20%
Sweet!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;memory-management&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-management&quot; aria-label=&quot;Anchor link for: memory-management&quot;&gt;Memory Management&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Let JAX manage GPU memory dynamically&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;XLA_PYTHON_CLIENT_PREALLOCATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Allocate only 70% of VRAM to leave headroom for JIT compilation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;XLA_PYTHON_CLIENT_MEM_FRACTION&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0.70&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use async allocator to reduce fragmentation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;TF_GPU_ALLOCATOR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;cuda_malloc_async&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Disable float64 (slower on Tensor Cores)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;JAX_ENABLE_X64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;False&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Memory tuning is critical for FBPINNs:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Preallocation vs. dynamic allocation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Preallocate: JAX reserves all VRAM at startup&lt;&#x2F;li&gt;
&lt;li&gt;Dynamic: JAX allocates only when needed&lt;&#x2F;li&gt;
&lt;li&gt;For research, dynamic is better (flexibility for variable batch sizes)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Memory fraction:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;V100 has 16 GB VRAM&lt;&#x2F;li&gt;
&lt;li&gt;0.70 × 16 GB = 11.2 GB for arrays&lt;&#x2F;li&gt;
&lt;li&gt;Remaining 4.8 GB: JIT compilation, temporary buffers&lt;&#x2F;li&gt;
&lt;li&gt;My FBPINNs code has large network weights and grouped subdomain metadata (varies, but I hit the wall pretty fast)&lt;&#x2F;li&gt;
&lt;li&gt;If I set to 0.90, JIT compilation fails with OOM when recompiling&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Async allocator (&lt;code&gt;cuda_malloc_async&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Default CUDA allocator uses a buddy-block system (causes fragmentation)&lt;&#x2F;li&gt;
&lt;li&gt;Async allocator uses a more efficient pool strategy&lt;&#x2F;li&gt;
&lt;li&gt;Benefit: ~20-30% reduction in allocation latency, fewer OOM errors&lt;&#x2F;li&gt;
&lt;li&gt;No downside for training (not used for inference)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Float32 vs Float64:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;V100 Tensor Cores: 125 TFLOPS (float32), 4 TFLOPS (float64)&lt;&#x2F;li&gt;
&lt;li&gt;32x speedup by using float32&lt;&#x2F;li&gt;
&lt;li&gt;For PINNs, float32 is sufficient (physics-informed loss provides regularization)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This first of all prevents OOM (total pain in my ass) and also enables 2-3x faster math. Crazzyyy…&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compilation-caching&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#compilation-caching&quot; aria-label=&quot;Anchor link for: compilation-caching&quot;&gt;Compilation Caching&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;JAX_ENABLE_COMPILATION_CACHE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;environ&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;JAX_COMPILATION_CACHE_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.jax_cache&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How it works:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;In the first run JAX compiles my FBPINN update function (around 10-30 seconds)&lt;&#x2F;li&gt;
&lt;li&gt;Compilation artifact saved to the disk (&lt;code&gt;.jax_cache&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;And in the second run, JAX loads cached artifact, skips compilation&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Quite simple isnt it! Run the same job twice?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Without cache: 30s + 50,000 steps × 0.5s = 25030 seconds&lt;&#x2F;li&gt;
&lt;li&gt;With cache: 0s + 50,000 steps × 0.5s = 25000 seconds&lt;&#x2F;li&gt;
&lt;li&gt;Research is iterative development. Restarting job to tweak hyperparameters, I get instant speedup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;algorithmic-optimizations-due-to-memory&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#algorithmic-optimizations-due-to-memory&quot; aria-label=&quot;Anchor link for: algorithmic-optimizations-due-to-memory&quot;&gt;Algorithmic optimizations due to Memory&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;grouped-subdomain-evaluation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#grouped-subdomain-evaluation&quot; aria-label=&quot;Anchor link for: grouped-subdomain-evaluation&quot;&gt;Grouped Subdomain Evaluation&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The training domain is split into 75 overlapping subdomains. Each subdomain has its own neural network (75 networks total).&lt;&#x2F;p&gt;
&lt;p&gt;Naive approach would have been:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; m&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;M&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; p&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; domain_points&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;p&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; network&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;m&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;x&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;p&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Memory: O(M × P × d) where P = number of test points, d = spatial dimensions. For this setup 75 × 262,144 × 3 × 4 bytes = 300 GB (well, i dont have infinite money glitch for sure)
So, I used some tricks up my sleve :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Precomputed metadata: which points belong to which subdomains&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;g_n_idx&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; g_n_mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; grouped_metadata&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Vectorized evaluation: all 75 subdomains in parallel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;us_g&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ws_g&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; us_raw_g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; vmap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;_model_over_subdomains&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; in_axes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;f&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    all_params&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x_batch&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;g_n_idx&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; g_n_mask&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Hardware reduction: combine contributions per point&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;u_sum_local&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ops&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;segment_sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;us_masked&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; idx_flat&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; num_segments&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;num_p_total&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wp_sum_local&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ops&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;segment_sum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ws_masked&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; idx_flat&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; num_segments&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;num_p_total&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Global weighted average&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;u_local_norm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; u_sum_local&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; jnp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;maximum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;wp_sum_local&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1e-5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Quirks you ask?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;On-the-fly indexing: Instead of creating &lt;code&gt;(M, max_P, d)&lt;&#x2F;code&gt; array, index into &lt;code&gt;x_batch&lt;&#x2F;code&gt; dynamically&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Memory: O(P × d) = 262,144 × 3 × 4 = 3 MB&lt;&#x2F;li&gt;
&lt;li&gt;Savings is nuts: 300 GB to 3 MB&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Vectorized evaluation via &lt;code&gt;vmap&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically distributes subdomain evaluation across GPU cores&lt;&#x2F;li&gt;
&lt;li&gt;JAX compiles to parallel kernels&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Hardware-accelerated reduction via segment_sum:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GPU tree-reduction algorithm&lt;&#x2F;li&gt;
&lt;li&gt;O(log P) parallel steps instead of O(P) sequential&lt;&#x2F;li&gt;
&lt;li&gt;Speed: 10-20x faster than Python loops&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I get 3-5x faster than naive sequential evaluation + memory enables 262k-point test grids. Win.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;chunked-processing-for-large-validations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#chunked-processing-for-large-validations&quot; aria-label=&quot;Anchor link for: chunked-processing-for-large-validations&quot;&gt;Chunked Processing for Large Validations&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;During validation, I evaluate the FBPINN on a fine test grid (e.g., 128×128×16 = 262k points):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;chunk_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 25000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Process 25k points at a time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; chunk_start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_points&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; chunk_size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    chunk_end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk_start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; chunk_size&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_points&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    abs_error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jnp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;abs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u_exact_flat&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;chunk_start&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;chunk_end&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; u_test_flat&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;chunk_start&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;chunk_end&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The issue is that validation grid might not fit in VRAM (even with grouped evaluation). So, the chunks of 25k points is around ~15 MB per chunk that fits comfortably. This enables high-resolution validation without OOM, ~5-10% overhead from loop.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pipelined-updates&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#pipelined-updates&quot; aria-label=&quot;Anchor link for: pipelined-updates&quot;&gt;Pipelined Updates&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;My &lt;code&gt;run.sh&lt;&#x2F;code&gt; requests multiple GPUs. Lets stick with simple 2 for this blog. Without careful coordination, multi-GPU training can be slow due to communication overhead.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;MULTI_STEP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;ACC_STEPS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _update_pmap_impl&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; fp&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; static_params_local&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; start_step&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _acc_block&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;carry&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        c_aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; curr_step&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; carry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; _inner_step&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;i_carry&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            i_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_step&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_grads&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_loss&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; i_carry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            l&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; value_and_grad&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;FBPINN_loss&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; argnums&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            n_grads&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tree&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;lambda&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; y&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_grads&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; g&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;i_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_step&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_grads&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i_loss&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Gradient accumulation loop (10 steps)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        init_g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tree&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;jnp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;zeros_like&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c_ap&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span&gt;next_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_step&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sum_g&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sum_l&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            _inner_step&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            (&lt;&#x2F;span&gt;&lt;span&gt;c_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; curr_step&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; init_g&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;            None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;ACC_STEPS&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        final_g&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tree&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;lambda&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ACC_STEPS&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sum_g&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Single optimizer update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        updates&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_aos&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; optimiser_fn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;final_g&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c_aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; next_ap&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        n_ap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; optax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;apply_updates&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;next_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; updates&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n_aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; n_step&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; final_l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Outer loop (10 blocks)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    (&lt;&#x2F;span&gt;&lt;span&gt;final_aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; final_ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; block_losses&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;scan&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        _acc_block&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        (&lt;&#x2F;span&gt;&lt;span&gt;aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ap&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start_step&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;        None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;MULTI_STEP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; ACC_STEPS&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; block_losses&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; final_aos&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; final_ap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why this is fast:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Nested loops structure:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Inner &lt;code&gt;scan&lt;&#x2F;code&gt;: 10 gradient accumulation steps (NO optimizer update)&lt;&#x2F;li&gt;
&lt;li&gt;Outer &lt;code&gt;scan&lt;&#x2F;code&gt;: 10 blocks of 10 steps each = 100 total steps&lt;&#x2F;li&gt;
&lt;li&gt;So the benefit: 1 optimizer update per 10 steps instead of 1 per step&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Gradient accumulation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Accumulate gradients: &lt;code&gt;grad_total += grad_step&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;After 10 steps, apply optimizer once: &lt;code&gt;param -= lr * grad_total &#x2F; 10&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Mathematically equivalent to 10 smaller updates, but faster GPU execution&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;JIT compilation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Entire 100-step block compiles to single XLA function&lt;&#x2F;li&gt;
&lt;li&gt;Reduces Python overhead from 100 calls to 1 call&lt;&#x2F;li&gt;
&lt;li&gt;100 steps × 0.5s&#x2F;step = 50s with Python overhead to 50s without (if overhead was 1%)&lt;&#x2F;li&gt;
&lt;li&gt;More realistic: 100 steps with overhead = 55s, without = 50s to 10% speedup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Multi-GPU coordination:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;jax.pmap&lt;&#x2F;code&gt; distributes the function across 2 GPUs&lt;&#x2F;li&gt;
&lt;li&gt;Within the pmap, each GPU owns disjoint subdomains&lt;&#x2F;li&gt;
&lt;li&gt;Synchronization happens via &lt;code&gt;jax.lax.pmean&lt;&#x2F;code&gt; (hardware all-reduce)&lt;&#x2F;li&gt;
&lt;li&gt;By processing 100 steps in one pmap call, you reduce sync frequency&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Overall 2-3x speedup with 2 GPUs&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hardware-native-subdomain-sharding&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hardware-native-subdomain-sharding&quot; aria-label=&quot;Anchor link for: hardware-native-subdomain-sharding&quot;&gt;Hardware-Native Subdomain Sharding&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u_sync&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;x_batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1. Local evaluation on each GPU&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    outs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; FBPINN_model&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_params&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x_batch&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; takes&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; model_fns&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2. Hardware sync: GPU0 and GPU1 combine results&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;takes&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u_sum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; wp_sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;psum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;outs&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; axis_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;devices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3. Global weighted average&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        wp_total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jnp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;maximum&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;wp_sum&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1e-5&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u_global&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; u_sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span&gt; wp_total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        u_global&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; model_fns&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_params&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x_batch&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; u_global&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; u_global&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How sharding works:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Partition of Unity (PoU): Each subdomain has a smooth window function &lt;code&gt;w_m(x)&lt;&#x2F;code&gt; that sums to 1&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;At any point: &lt;code&gt;sum_m w_m(x) = 1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Global solution: &lt;code&gt;u(x) = sum_m w_m(x) * u_m(x)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;GPU distribution:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GPU0 owns subdomains 1-37, computes: &lt;code&gt;u_sum_0 = sum_{m=1}^{37} w_m(x) * u_m(x)&lt;&#x2F;code&gt;, &lt;code&gt;w_sum_0 = sum_{m=1}^{37} w_m(x)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;GPU1 owns subdomains 38-75, computes: &lt;code&gt;u_sum_1 = sum_{m=38}^{75} w_m(x) * u_m(x)&lt;&#x2F;code&gt;, &lt;code&gt;w_sum_1 = sum_{m=38}^{75} w_m(x)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Hardware synchronization:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;jax.lax.psum&lt;&#x2F;code&gt; all-reduces: &lt;code&gt;u_sum = u_sum_0 + u_sum_1&lt;&#x2F;code&gt;, &lt;code&gt;w_sum = w_sum_0 + w_sum_1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Runs on NVLink (~300 GB&#x2F;s)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Final assembly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;u_global = u_sum &#x2F; w_sum&lt;&#x2F;code&gt; (per-point weighted average)&lt;&#x2F;li&gt;
&lt;li&gt;Apply constraints (boundary conditions)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, a near-linear scaling (1.8-2x with 2 GPUs)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nccl-tuning&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nccl-tuning&quot; aria-label=&quot;Anchor link for: nccl-tuning&quot;&gt;NCCL tuning&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_P2P_DISABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;          #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Enable P2P over NVLink&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_IB_DISABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;           #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; No InfiniBand&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_MIN_NCHANNELS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;       #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 32 channels for parallelism&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NCCL_BUFFSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;8388608&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;       #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 8 MB buffers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;NCCL parameters explained:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;P2P: GPU-to-GPU direct memory access&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Alternative: CPU-mediated (GPU → CPU → GPU, much slower)&lt;&#x2F;li&gt;
&lt;li&gt;My V100s are on the same PCIe switch, so P2P is efficient&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Min channels: Multiple parallel communication paths&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;32 channels means 32 parallel “streams” of all-reduce operations&lt;&#x2F;li&gt;
&lt;li&gt;Better GPU utilization on large collectives&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Buffer size: Tradeoff between latency and memory overhead&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;8 MB is tuned for V100 bandwidth (~900 GB&#x2F;s effective)&lt;&#x2F;li&gt;
&lt;li&gt;Smaller = lower latency, larger = better throughput&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Thus, ~20-30% faster multi-GPU communication&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fast-prng&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fast-prng&quot; aria-label=&quot;Anchor link for: fast-prng&quot;&gt;Fast PRNG&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;jax_enable_custom_prng&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;jax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;jax_default_prng_impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;threefry2x32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ThreeFry is a fast parallel PRNG. Benefits:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;~5-10% speedup in sampling-heavy workloads and Minimal overhead for random point sampling&lt;&#x2F;li&gt;
&lt;li&gt;Disables NaN checks (small overhead, but adds up over millions of ops)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;memory-hierarchy-optimizations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#memory-hierarchy-optimizations&quot; aria-label=&quot;Anchor link for: memory-hierarchy-optimizations&quot;&gt;Memory Hierarchy Optimizations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;chunked-pde-residual-computation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#chunked-pde-residual-computation&quot; aria-label=&quot;Anchor link for: chunked-pde-residual-computation&quot;&gt;Chunked PDE Residual Computation&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Computing PDE residuals for large batches (e.g., 10,000+ points) simultaneously creates a working set that exceeds the GPU’s L2 cache (6MB on V100). This causes &lt;strong&gt;cache thrashing&lt;&#x2F;strong&gt;, where data is repeatedly evicted and re-fetched from slow global memory. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.arccompute.io&#x2F;arc-blog&#x2F;optimizing-gpu-performance-for-ai-companies-strategies-to-reduce-waste-and-enhance-efficiency&quot;&gt;Research shows underutilizing L2 cache can cause 160–176% slowdown&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;To push performance beyond standard JAX JIT compilation, I implemented three targeted optimizations designed to maximize &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.arccompute.io&#x2F;arc-blog&#x2F;how-to-harness-l2-cache-optimizations-for-nvidia-gpus&quot;&gt;L2 cache residency&lt;&#x2F;a&gt; and minimize expensive High Bandwidth Memory (HBM) transactions.&lt;&#x2F;p&gt;
&lt;p&gt;As FBPINN residual evaluations have low arithmetic intensity (few FLOPs per byte loaded). By processing in chunks that fit in L2, we can effectively increase the operational intensity by avoiding repeated DRAM fetches for the same parameters, keeping them ‘hot’ in cache.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Naive approach: Large working set evicts L2 cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Working Set ~= 10,000 points * (inputs + grads + activations) &amp;gt; 6MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;residuals&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; compute_pde_residual&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_points&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; High DRAM traffic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Optimized approach: Blocked execution for L2 residency&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Working Set ~= 2,048 points &amp;lt; 6MB (Cache Hit!)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;residuals&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; jnp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;concatenate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    compute_pde_residual&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;chunk&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; chunk&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_points&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2048&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This gives us speedup of about 20-30% for large batch sizes and L2 Hit Rate increases from ~50% to &amp;gt;85%. Another win!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;subdomain-batching&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#subdomain-batching&quot; aria-label=&quot;Anchor link for: subdomain-batching&quot;&gt;Subdomain Batching&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The problem is that FBPINNs evaluate multiple sub-networks (subdomains). Evaluating all 75+ subdomains in parallel loads all their unique parameters into memory at once (~15MB), blowing out the 6MB L2 cache. So, we batch the subdomains themselves. By evaluating only 20 subdomains at a time, we ensure their combined parameters remain resident in L2 for the duration of the compute kernel.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Naive: Thrashing L2 with all subdomains&amp;#39; params&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;vmap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;evaluate_subdomain&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_75_subdomains&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Optimized: Tiled execution&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Keeps active parameter set &amp;lt; L2 Cache Size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; batch&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; batch_subdomains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;all_75_subdomains&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vmap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;evaluate_subdomain&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this I reduced by ~50% due to fewer DRAM reads, and got a speedup of 15-25% on problems with high domain counts.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;spatial-sorting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#spatial-sorting&quot; aria-label=&quot;Anchor link for: spatial-sorting&quot;&gt;Spatial Sorting&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Collocation points are often sampled randomly. This leads to uncoalesced memory access—thread 0 reads address $A$, thread 1 reads address $A+10000$. This wastes memory bandwidth and causes TLB (Translation Lookaside Buffer) misses.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-not-optimized&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-not-optimized&quot; aria-label=&quot;Anchor link for: what-s-not-optimized&quot;&gt;What’s not optimized&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My code uses &lt;code&gt;pmap&lt;&#x2F;code&gt; (data parallelism over GPU axis) instead of DDP because:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;My architecture is fundamentally model-parallel (subdomains)&lt;&#x2F;li&gt;
&lt;li&gt;DDP is better for replicated models, worse for domain decomposition&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Also, no Quantization tricks as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;SIREN networks are fully dense&lt;&#x2F;li&gt;
&lt;li&gt;Float32 is necessary for precision-sensitive PDE solving&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;some-more-nerdy-thoughts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-more-nerdy-thoughts&quot; aria-label=&quot;Anchor link for: some-more-nerdy-thoughts&quot;&gt;Some more nerdy thoughts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.aleksagordic.com&#x2F;blog&#x2F;matmul&quot;&gt;Understanding NVIDIA GPUs is necessary if you want to do scientific ML&lt;&#x2F;a&gt;. I will maybe someday &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siboehm.com&#x2F;articles&#x2F;22&#x2F;CUDA-MMM&quot;&gt;write my own performant GPU kernels&lt;&#x2F;a&gt; (or maybe make an agent do that?).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.arch.jhu.edu&#x2F;en&#x2F;latest&#x2F;2_Common_Tasks&#x2F;GPU_Computing.html&quot;&gt;GPU performance issues are rarely about raw compute&lt;&#x2F;a&gt;. Modern GPUs have huge peak FLOPs, but they only reach it when:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Data is already in GPU memory.&lt;&#x2F;li&gt;
&lt;li&gt;Kernels are queued without gaps.&lt;&#x2F;li&gt;
&lt;li&gt;Communication is overlapped with compute.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If input data, gradients, or activations arrive late (I&#x2F;O, network, host scheduling), the GPU finishes its current work and then sits idle waiting for the next batch. Utilization drops, but not because the GPU is weak, because the pipeline upstream is slow or bursty.&lt;&#x2F;p&gt;
&lt;p&gt;Even if FLOP count is the same, a small regression in memory layout can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Drop effective bandwidth.&lt;&#x2F;li&gt;
&lt;li&gt;Increase latency per kernel.&lt;&#x2F;li&gt;
&lt;li&gt;Cause whole pipelines to run slower, dropping utilization and increasing p95&#x2F;p99 latency.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In distributed training or multi‑GPU jobs we use NCCL all‑reduce&#x2F;all‑gather for gradients, parameters, or activations :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Each rank (GPU) must participate (Collectives are synchronized)&lt;&#x2F;li&gt;
&lt;li&gt;If one GPU is slightly slower (data pipeline, kernel, or scheduling), others finish early and then wait at the barrier.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That little imbalance cascades:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;All GPUs idle during the slowest all‑reduce.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2507.04786v1&quot;&gt;As step time increases, any latency spikes at the slowest rank show up as cluster‑wide spikes&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So I can have perfectly fine raw compute, but a subtle change (e.g., different batch size, skewed data, contention on one node) makes one rank lag, and utilization drops everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;Within a node, GPUs talk over NVLink&#x2F;NVSwitch. NVLink is fast, but still finite! Once a link is saturated:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Communication for collectives&#x2F;halo exchanges queues up.&lt;&#x2F;li&gt;
&lt;li&gt;Kernels that depend on that data start later.&lt;&#x2F;li&gt;
&lt;li&gt;GPUs wait more often on communication, so compute units are idle while the link drains.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Again, compute capacity didn’t change! the interconnect became the bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;All of these issues—memory access regressions, collective sync stalls, NVLink congestion, CPU jitter—cause short idle periods and periodic long stalls. Even if average utilization doesn’t plummet, tail latency and throughput do! For online inference P95&#x2F;P99 latency jumps because some requests hit a stalled collective or a data‑starved GPU. For training time‑per‑step grows; training runs longer. You pay for GPU‑hours where the GPUs are not fully used, inflating infra cost.&lt;&#x2F;p&gt;
&lt;p&gt;Optimizing AI systems is mostly about feeding GPUs consistently (data, comms, scheduling) and coordinating them well! Raw FLOPs are rarely the limiting factor. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.whitefiber.com&#x2F;blog&#x2F;how-to-plan-source-and-optimize-gpu-capacity-for-ai-deployment&quot;&gt;Optimize relentellesly guys, GPUs are darn expensive&lt;&#x2F;a&gt;!!! Hell, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tigerabrodi.blog&#x2F;why-your-gpu-hates-png&quot;&gt;my GPUs hate PNGs&lt;&#x2F;a&gt; ;)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;continuous-profiling&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#continuous-profiling&quot; aria-label=&quot;Anchor link for: continuous-profiling&quot;&gt;Continuous Profiling&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In high-performance training and inference pipelines, identifying the root cause of such issues is very challenging. When CUDA kernels underperform or Tensor Core utilization drops, engineers often reach for PyTorch Profiler or NVIDIA Nsight. But I dont feel very happy using these tools as a begineer. They operate at the level of individual processes or isolated GPU nodes, making frictionless, cluster-wide GPU visibility nearly impossible. This fragmented view means stitching together multiple tools, managing complex instrumentation, and manually correlating traces across nodes. It’s unsustainable!! Continuous profiling GPU has an observability tax. Continuous GPU profiling is essential for inference heavy pipelines because system entropy is driven by user requests. This is especially critical in disaggregated deployments that split prefill and decode phases, where performance can vary unpredictably.&lt;&#x2F;p&gt;
&lt;p&gt;AI will surely come for rescue here sometime in 2026 I bet!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;have-to-stop-writing-now&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#have-to-stop-writing-now&quot; aria-label=&quot;Anchor link for: have-to-stop-writing-now&quot;&gt;Have to stop writing now..&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lilianweng.github.io&#x2F;posts&#x2F;2021-09-25-train-large&#x2F;&quot;&gt;It’s fun to train such large ML models on many GPUs&lt;&#x2F;a&gt;. I am finding ML Infrastructure and overall Software Engineering much harder than the actual ML itself. What a joke! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;alexzhang13.github.io&#x2F;blog&#x2F;2024&#x2F;efficient-dl&#x2F;&quot;&gt;When I look back, the advancements of Deep Learning over the years is simply astounding&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Need to sleep now. 2:22 AM already, and I have quiz for Moral Philosophy tomorrow!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Rusty path to Secure Metrics in Ambient Mesh</title>
          <pubDate>Fri, 23 May 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/istio-lfx/</link>
          <guid>https://harsh-ps-2003.github.io/writes/istio-lfx/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/istio-lfx/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;&quot;&gt;Istio&lt;&#x2F;a&gt; is widely recognized as the most popular, powerful, and trusted &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.solo.io&#x2F;topics&#x2F;service-mesh&#x2F;service-mesh-architecture&quot;&gt;service mesh&lt;&#x2F;a&gt; in the cloud native ecosystem and is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;cV6JFq8XNZQ?si=wmSUz605Dl4km4Az&quot;&gt;extensively used in Production since it’s inception&lt;&#x2F;a&gt;. Fortunately, I got the opportunity to intern at Istio (managed CNCF and spun out of Google), and man my brain transitioned from a code-monkey to a divine architect in mere span of 3 months.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-did-i-do&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-did-i-do&quot; aria-label=&quot;Anchor link for: what-did-i-do&quot;&gt;What did I do?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;It feels surreal to know that the work I did during my internship will have a outsized impact on everyone using Istio’s ztunnel. Imagine, everytime someone scrapes ztunnel, they use one feature designed and implemented by me. Wowwwwww….&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Before my work, ztunnel metrics were exposed in plaintext, trusting any client that could reach the port - scraping metrics followed &lt;code&gt;Prometheus -&amp;gt; HTTP -&amp;gt; Ztunnel Metrics Server&lt;&#x2F;code&gt; :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Direct HTTP connection&lt;&#x2F;li&gt;
&lt;li&gt;No encryption&lt;&#x2F;li&gt;
&lt;li&gt;No authentication&lt;&#x2F;li&gt;
&lt;li&gt;No policy enforcement&lt;&#x2F;li&gt;
&lt;li&gt;Simple but insecure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I added support for TLS (mTLS via HBONE tunneling) in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel?tab=readme-ov-file#metrics&quot;&gt;metrics endpoint in the ztunnel in Shared Proxy Mode of Istio’s Ambient Dataplane Mode&lt;&#x2F;a&gt;. Lots of buzzwords right ( ՞۝՞)&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I naively thought the solution would be straightforward - add a new mTLS-enabled metrics server to ztunnel. This seemed logical - we need secure metrics, so let’s add TLS. I started implementing a separate server that would:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Listen on a dedicated port&lt;&#x2F;li&gt;
&lt;li&gt;Handle TLS&#x2F;mTLS directly&lt;&#x2F;li&gt;
&lt;li&gt;Serve metrics over the secure connection&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;However, this approach had significant drawbacks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It would bypass ztunnel’s existing inbound logic&lt;&#x2F;li&gt;
&lt;li&gt;It would require duplicating certificate management code&lt;&#x2F;li&gt;
&lt;li&gt;It would create a separate security model from the rest of the mesh&lt;&#x2F;li&gt;
&lt;li&gt;And, most importantly, it would break the transparency principle - &lt;em&gt;Prometheus would need to be configured specifically for mTLS&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;After I made a draft PR implementing the new mTLS-metrics server, then I realized that I should take a break and actually think a lot more. The feedback from Istio community was great, and helped me grasp the context and the sheer scale of the system that I was working on.&lt;&#x2F;p&gt;
&lt;p&gt;Service mesh should provide &lt;strong&gt;zero-trust security&lt;&#x2F;strong&gt; by default - where no service is trusted until proven otherwise, provides security and observability without requiring changes to the application code, provides a consistent security model across all services in the mesh, treats all services uniformly acting as platform for consistent service-to-service communication, allowing progressive enhancement of service capabilities.&lt;&#x2F;p&gt;
&lt;p&gt;The “aha moment” came when I realized that ztunnel itself could be treated as a workload in the mesh, so I can extend the service mesh to include ztunnel itself. This was a profound insight because:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It aligned with Istio’s “everything is a workload” philosophy&lt;&#x2F;li&gt;
&lt;li&gt;It meant we could leverage existing mesh capabilities rather than building new ones&lt;&#x2F;li&gt;
&lt;li&gt;It maintained transparency for both ztunnel and Prometheus&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, now its &lt;code&gt;Prometheus -&amp;gt; HTTP -&amp;gt; Local Ztunnel -&amp;gt; HBONE -&amp;gt; Target Ztunnel -&amp;gt; Metrics Server&lt;&#x2F;code&gt; :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus still makes a plain HTTP request (transparency - dosen’t need to know about TLS or HBONE)&lt;&#x2F;li&gt;
&lt;li&gt;The request is intercepted by iptables rules on the node where Prometheus is running (local ztunnel on the same node)&lt;&#x2F;li&gt;
&lt;li&gt;Ztunnel recognizes this is a request to another Ztunnel pod (target ztunnel being scraped) in the mesh&lt;&#x2F;li&gt;
&lt;li&gt;It automatically upgrades the connection to HBONE (HTTP&#x2F;2 over mTLS)&lt;&#x2F;li&gt;
&lt;li&gt;This happens transparently to Prometheus - it’s still just making a regular HTTP request&lt;&#x2F;li&gt;
&lt;li&gt;Target ztunnel processes through standard inbound path, forwarding to internal metrics server, sending back through same tunnel&lt;&#x2F;li&gt;
&lt;li&gt;Full Network Policy enforcement&lt;&#x2F;li&gt;
&lt;li&gt;Secure but transparent to both ends&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Every metrics request must prove its identity through mTLS, and authorization policies can control exactly which Prometheus instances can access the metrics&lt;&#x2F;p&gt;
&lt;p&gt;The key components that made this possible is :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Ambient Redirection&lt;&#x2F;em&gt; - The &lt;code&gt;ambient.istio.io&#x2F;redirection: enabled&lt;&#x2F;code&gt; label on ztunnel pods tells the mesh that ztunnel should be treated as a workload and enables automatic traffic interception and HBONE upgrade.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Identity Management&lt;&#x2F;em&gt; - Ztunnel uses Kubernetes Downward API to get its identity which is used to request certificates from Istiod. Same process as any other workload in the mesh.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Inbound Handler&lt;&#x2F;em&gt; - Existing component that already handles HBONE connectionsa and processes mTLS termination.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;No new code needed! Elegant…&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fun thing - I increased the ztunnel binary size form 15mb to 16mb, which lead to CI failure. I had a fun time watching my mentor figure out what the heck just happened in Weekly Standup ( ^^)Y&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Now for a deeper look you can take a look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;document&#x2F;d&#x2F;19vMr22inhLAPjWcVJkZWiG_GY6ZG3PLxG9QqAmIlnIc&#x2F;edit?usp=sharing&quot;&gt;Design Doc&lt;&#x2F;a&gt; for the feature. Most of my time went into thinking about the design, instead of coding it up. I also created a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;document&#x2F;d&#x2F;1-TFA0FnmHgsL0IOFIn8Vm5_klDFZkAqg31oX1-p88Pw&#x2F;edit?usp=sharing&quot;&gt;beautiful Internship report&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-did-i-learn&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-did-i-learn&quot; aria-label=&quot;Anchor link for: what-did-i-learn&quot;&gt;What did I learn?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Due to my prior internship experience in Rust, the compiler was very friendly with me this time ■D＼(^^ )&lt;&#x2F;p&gt;
&lt;p&gt;This time, I learnt a lot of Kubernetes, Helm, low-level TCP&#x2F;IP, HTTP&#x2F;S, certificate management, debugging docker containers in different namespaces in k8s clusters, about service mesh and why they are adopted at the first place, and more.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;rVNPnHeGYBE?si=zVFql6-qTD_tn1qI&quot;&gt;Learning Service Mesh&lt;&#x2F;a&gt; was very daunting for a new-comer like me! So many new terminology gets thrown here and there! This &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KUHzxTCe5Uc&quot;&gt;tutorial&lt;&#x2F;a&gt; on Istio’s Service Mesh helped me grasp things quite well! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;cB611FtjHcQ?si=z85aMnm2Amj-HOQ4&quot;&gt;Life of a packet in Istio is very interesting&lt;&#x2F;a&gt; ヽ(o⌣oヾ)&lt;&#x2F;p&gt;
&lt;p&gt;This project taught me several valuable lessons about service mesh:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Transparency is the Key&lt;&#x2F;em&gt; - The beauty of service mesh is that applications don’t need to know about security. Prometheus still makes plain HTTP requests and the Ztunnel’s metrics server still serves plain HTTP. The mesh handles all the security complexity&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Configuration Over Code&lt;&#x2F;em&gt; - Instead of writing new security code, we configured ztunnel to be a workload leveraging existing, well-tested components reducing complexity and potential bugs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Mesh Philosophy&lt;&#x2F;em&gt; - Understanding that service mesh is about treating everything as a workload. Even infrastructure components like ztunnel can benefit from mesh capabilities. The mesh should be the security boundary, not individual components.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What’s really cool about this solution is that it demonstrates the power of service mesh architecture:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We didn’t need to modify the metrics server&lt;&#x2F;li&gt;
&lt;li&gt;We didn’t need to configure Prometheus&lt;&#x2F;li&gt;
&lt;li&gt;We didn’t need to write new security code&lt;&#x2F;li&gt;
&lt;li&gt;We just needed to tell the mesh “hey, ztunnel is a workload too”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is exactly why organizations adopt service mesh - it provides security and observability without changing applications which stay simple and focused on core functionality. No need for applications to implement complex security protocols. The fact that we could extend this to ztunnel itself shows how powerful and flexible the architecture is.&lt;&#x2F;p&gt;
&lt;p&gt;So, I told the tale of my internship, but if you want to learn more, you can read further about the ztunnel internals….&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-what-s-ztunnel&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-what-s-ztunnel&quot; aria-label=&quot;Anchor link for: but-what-s-ztunnel&quot;&gt;But what’s Ztunnel?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Ztunnel (Zero Trust Tunnel) is a core component of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;latest&#x2F;blog&#x2F;2022&#x2F;introducing-ambient-mesh&#x2F;&quot;&gt;Istio Ambient Mesh&lt;&#x2F;a&gt;. It acts as a secure transport proxy running on each node. Its main job is to handle traffic redirection and establish secure &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;latest&#x2F;docs&#x2F;ambient&#x2F;architecture&#x2F;hbone&#x2F;&quot;&gt;HBONE tunnels&lt;&#x2F;a&gt; between different pods using mutual TLS (mTLS) based on workload identities - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.solo.io&#x2F;blog&#x2F;understanding-istio-ambient-ztunnel-and-secure-overlay&quot;&gt;SPIFFE&lt;&#x2F;a&gt;. It manages traffic without requiring traditional sidecars for every application pod, receiving configuration dynamically from the Istio control plane (Istiod) via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.envoyproxy.io&#x2F;docs&#x2F;envoy&#x2F;latest&#x2F;api-docs&#x2F;xds_protocol&quot;&gt;xDS&lt;&#x2F;a&gt;. It can operate in a shared mode, serving multiple pods on a node.&lt;&#x2F;p&gt;
&lt;p&gt;Plenty of cool blogs from the cool folks at CNCF to learn more :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;linsun&quot;&gt;Lin Sun’s&lt;&#x2F;a&gt; - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;latest&#x2F;blog&#x2F;2023&#x2F;rust-based-ztunnel&#x2F;&quot;&gt;blog introducing ztunnel for Istio’s Ambient Mesh&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;distributethe6ix&quot;&gt;Marino Wijay’s&lt;&#x2F;a&gt; - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.solo.io&#x2F;blog&#x2F;understanding-istio-ambient-ztunnel-and-secure-overlay&quot;&gt;blog with cool diagrams about it&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Well, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;master&#x2F;ARCHITECTURE.md&quot;&gt;the architecture is explained in short in the repository&lt;&#x2F;a&gt;, but that’s just too less information for me. So, as I already intended to deep-dive into the ztunnel codebase, I am writing about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;understanding-its-architecture&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#understanding-its-architecture&quot; aria-label=&quot;Anchor link for: understanding-its-architecture&quot;&gt;Understanding its Architecture&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most fundamental job of ztunnel is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tetrate.io&#x2F;blog&#x2F;transparent-traffic-interception-in-istio-ambient-mode-a-comprehensive-explanation&#x2F;?utm_content=318241177&amp;amp;utm_medium=social&amp;amp;utm_source=twitter&amp;amp;hss_channel=tw-998918265177952259&quot;&gt;Traffic Interception &amp;amp; Routing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;On Linux, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;socket.rs#L61&quot;&gt;orig_dst_addr&lt;&#x2F;a&gt; uses the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;setsockopt.2.html&quot;&gt;getsockopt system call&lt;&#x2F;a&gt; with IPv4&#x2F;v6 socket options. These options allow a program to retrieve the original destination address of a connection that was redirected by the netfilter framework (using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;NAdJojxENEU?si=lySWydWtqlO83x7m&quot;&gt;iptables with REDIRECT&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;networking&#x2F;tproxy.txt&quot;&gt;TPROXY&lt;&#x2F;a&gt; targets).&lt;&#x2F;p&gt;
&lt;p&gt;For platforms other than Linux, ztunnel’s transparent interception capabilities relying on this mechanism would be limited or would require different OS-specific approaches.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;config.rs#L181&quot;&gt;Config&lt;&#x2F;a&gt; struct is the single source of truth for ztunnel’s runtime parameters. Once it’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;config.rs#L418&quot;&gt;constructed&lt;&#x2F;a&gt;, various parts of ztunnel will refer to it to make decisions.&lt;&#x2F;p&gt;
&lt;p&gt;It has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;config.rs#L142&quot;&gt;Shared and Dedicated Proxy Modes&lt;&#x2F;a&gt; built via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxyfactory.rs#L31&quot;&gt;ProxyFactory&lt;&#x2F;a&gt; :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                              +-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                              | Start |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                              +-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          +-------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          | Which Mode? |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          +-------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         &#x2F;               \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        &#x2F;                 \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       &#x2F;                   \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 Dedicated                Shared&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v                       v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------------+      +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           | Create Default |      | Get Pod&amp;#39;s    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           | SocketFactory  |      | NetNS        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------------+      +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v                       v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------------+      +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           | Packet Mark    |      | Create InPod |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           | Configured?    |      | SocketFactory|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +----------------+      +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              &#x2F;          \                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Yes           No                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |          +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             v            |          | Port Reuse   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     +--------------+     |          | Enabled?     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | Wrap with    |     |          +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | MarkFactory  |     |             &#x2F;        \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     +--------------+     |           Yes         No&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |            |          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |            v          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |    +--------------+   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |    | Wrap with    |   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |    | ReuseFactory |   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |    +--------------+   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |            |            |          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +------------+------------+----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 | Create LocalWorkload |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 | Information          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 | DNS Proxy Enabled?   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      &#x2F;            \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    Yes             No&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Create DNS Server|       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Get Resolver     |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 | Main Proxy Enabled?  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      &#x2F;            \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    Yes             No&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Create Connection|       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Manager          |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Create Proxy     |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Inputs           |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Create Proxy     |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +------------------+       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 | Return ProxyResult   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         +-----+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         | End |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         +-----+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;whats-this-hbone-thingy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#whats-this-hbone-thingy&quot; aria-label=&quot;Anchor link for: whats-this-hbone-thingy&quot;&gt;Whats this HBONE thingy?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;HBONE (HTTP-Based Overlay Network Encapsulation) is Istio specific thing which uses HTTP&#x2F;2 as foundational protocol (HTTP CONNECT and standard mTLS). It creates a virtual network layer on top of the existing physical network. This “overlay” is where our secure tunnels live. It takes regular application traffic (which is usually TCP traffic) and “wraps” or “encapsulates” it inside these HTTP&#x2F;2 streams.&lt;&#x2F;p&gt;
&lt;p&gt;HBONE wraps standard TCP traffic (what your applications speak) inside an HTTP&#x2F;2 stream. This HTTP&#x2F;2 stream is then secured using mutual TLS (mTLS). So all the traffic flowing through the HBONE tunnel (i.e., within the mTLS session) is encrypted. Eavesdroppers on the network cannot understand the data. Pod A and Pod B just use standard TCP. They are completely unaware of the mTLS and HTTP&#x2F;2 encapsulation happening underneath by ztunnel.&lt;&#x2F;p&gt;
&lt;p&gt;HTTP has a CONNECT method, traditionally used for proxying. HBONE cleverly reuses this. To establish a tunnel to a target pod, the source ztunnel sends an HTTP&#x2F;2 CONNECT request to the destination ztunnel.&lt;&#x2F;p&gt;
&lt;p&gt;Establishing an mTLS handshake and a new HTTP&#x2F;2 connection for every single small request between two pods would be slow and inefficient. To solve this, ztunnel implements sophisticated connection pooling for HBONE connections through the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;pool.rs#L50&quot;&gt;WorkloadHBONEPool&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If an existing, healthy, mTLS-secured HTTP&#x2F;2 connection to ztunnel is already in the pool and has spare capacity (HTTP&#x2F;2 allows many streams on one connection), that connection is reused. A new HTTP&#x2F;2 stream is created on that existing connection for the current request. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;h2&#x2F;client.rs#L36&quot;&gt;H2ConnectClient&lt;&#x2F;a&gt; represents an active, pooled HTTP&#x2F;2 client connection to a remote ztunnel.&lt;&#x2F;p&gt;
&lt;p&gt;The pool includes sophisticated mechanisms to manage connection lifecycle :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;pool.rs#L204&quot;&gt;When a new connection is needed, the pool ensures that only one task creates a connection for a given destination, even if many requests arrive simultaneously&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;h2&#x2F;client.rs#L77&quot;&gt;The pool tracks how many HTTP&#x2F;2 streams are active on each connection and won’t exceed the configured limits&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;pool.rs#L126&quot;&gt;Connections that aren’t used for a configurable period are automatically closed to free up resources&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;h2&#x2F;client.rs#L195&quot;&gt;HTTP&#x2F;2 connections use PING frames to verify connection health&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Outbound request needs   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| HBONE                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Check connection pool    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| for existing connection  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| to destination           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------+-------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   +---------+---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   v Connection        v No Connection &#x2F; At Capacity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+   +--------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Reuse existing |   | Try to acquire lock for  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| connection     |   | destination              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------------+   +------------+-------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |          +---------+---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |          |                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |          v Lock Acquired     v Lock Acquisition Failed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         +-----------------+  +--------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         | Create new mTLS |  | Wait briefly, then retry |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         | + HTTP&#x2F;2 conn   |  | pool check (go back up)  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         +-------+---------+  +------------+-------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                 |                          ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                 v                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         +-----------------+                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         | Add connection  |----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         | to pool         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |         +-------+---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                 v Connection Ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +--------+--------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | Create new      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | HTTP&#x2F;2 stream   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | Send HTTP&#x2F;2     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | CONNECT request |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | Wait for 200 OK |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | response        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | HTTP&#x2F;2 stream   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | ready for data  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By wrapping application TCP traffic in mTLS-secured HTTP&#x2F;2 streams, ztunnel provides strong authentication, encryption, and integrity for inter-pod communication, all without requiring any changes to the applications. Ztunnel transparently manages the creation, termination, and pooling of these secure tunnels.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-does-a-connection-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-a-connection-work&quot; aria-label=&quot;Anchor link for: how-does-a-connection-work&quot;&gt;How does a connection work?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;Proxy&lt;&#x2F;code&gt; struct orchestrates the different parts of ztunnel :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Proxy&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    inbound&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Inbound&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Handles inbound HBONE traffic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    inbound_passthrough&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; InboundPassthrough&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Handles inbound non-HBONE TCP traffic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    outbound&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Outbound&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Handles outbound traffic from local applications&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    socks5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Socks5&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Optional SOCKS5 proxy support&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    policy_watcher&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PolicyWatcher&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Watches for policy changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The pool tracks connection by workload key :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WorkloadKey&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; src_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Identity&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;       &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Source workload identity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; dst_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Identity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Destination workload identity&#x2F;identities&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; dst&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SocketAddr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Destination address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IpAddr&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Source IP address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Outbound Traffic&lt;&#x2F;em&gt;: When your application pod tries to send a message to another service, ztunnel intercepts this message before it leaves the node. It decides whether the outbound traffic needs to go directly via TCP, or HBONE tunneling or through Waypoint&#x2F;Gateway. The outbound’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;outbound.rs#L374&quot;&gt;build_request&lt;&#x2F;a&gt; handles the routing by constructing a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;outbound.rs#L584&quot;&gt;Request&lt;&#x2F;a&gt; with routing decisions made, and then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;outbound.rs#L152&quot;&gt;passed to appropriate protocol handler&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;*Inbound Traffic: When a message arrives at the node destined for one of your application pods, ztunnel also intercepts this message before it reaches the pod. If its wrapped in an HBONE tunneling (meaning it came from another ztunnel or a compatible component), it decrypts the traffic, verifies the identity of sender using Workload and Certificates, and then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound_passthrough.rs#L66&quot;&gt;forwards the plaintext TCP to local pod&lt;&#x2F;a&gt; after checking the security policies via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound.rs#L183&quot;&gt;serve_connect method&lt;&#x2F;a&gt;. When &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound.rs#L314&quot;&gt;building the inbound request&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound.rs#L458&quot;&gt;validation checks&lt;&#x2F;a&gt; ensure security, after which we &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound.rs#L539&quot;&gt;determine the actual socket address to forward the traffic to&lt;&#x2F;a&gt;. Before everything, TLS handshake happens &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;inbound.rs#L81&quot;&gt;verifying server and client identities via InboundCertProvider&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;inpod&#x2F;admin.rs#L32&quot;&gt;ProxyState&lt;&#x2F;a&gt; is the knowledge base that stores information about workloads and services.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;connection_manager.rs#L59&quot;&gt;ConnectionManager&lt;&#x2F;a&gt; enforces policies and tracks active inbound and outbound connections. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy.rs#L61&quot;&gt;SocketFactory&lt;&#x2F;a&gt; creates properly configured sockets for each connection type.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxy&#x2F;connection_manager.rs#L305&quot;&gt;PolicyWatcher&lt;&#x2F;a&gt; monitors for policy changes and updates the connection manager.&lt;&#x2F;p&gt;
&lt;p&gt;The flow of a connection :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------+        +--------+        +--------+        +--------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Pod A  |        | zt A   |        | zt B   |        | Pod B  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Node 1 |        | Node 1 |        | Node 2 |        | Node 2 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------+        +--------+        +--------+        +--------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | Request to B    |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |----------------&amp;gt;|                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Intercept Req   |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Analyze         |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Decide HBONE    |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Establish HBONE |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Tunnel          |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |----------------------------------&amp;gt;| Establish HBONE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Tunnel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Encrypted Req   |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |----------------------------------&amp;gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Receive &amp;amp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Decrypt Req&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Verify Identity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Plaintext Req&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |----------------&amp;gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |                 | Process Req&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 | Plaintext Resp  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |&amp;lt;----------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 | Encrypt Resp    |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 | Encrypted Resp  |&amp;lt;----------------|                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |&amp;lt;----------------------------------|                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | Decrypt Resp    |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    | Plaintext Resp  |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&amp;lt;----------------|                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |                 |                 |                 |                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The data forwarding is handled via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;copy.rs#L142&quot;&gt;copy_bidirectional&lt;&#x2F;a&gt; which efficiently shuttles bytes between two connections ensuring data flows smoothly once ztunnel has decided where it should go.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;workload-identities&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#workload-identities&quot; aria-label=&quot;Anchor link for: workload-identities&quot;&gt;Workload Identities&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state&#x2F;workload.rs#L224&quot;&gt;Workload&lt;&#x2F;a&gt; in ztunnel represents an instance of your application, typically a pod in Kubernetes.&lt;&#x2F;p&gt;
&lt;p&gt;Ztunnel helps manage cryptographic identities for the workloads running on its node using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;identity&#x2F;manager.rs#L42&quot;&gt;SPIFFE ID&lt;&#x2F;a&gt; - &lt;code&gt;spiffe:&#x2F;&#x2F;your-trust-domain&#x2F;ns&#x2F;your-namespace&#x2F;sa&#x2F;your-service-account&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To prove a workload actually owns a SPIFFE ID, it gets an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;azure&#x2F;iot-hub&#x2F;reference-x509-certificates&quot;&gt;X.509 certificate&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;identity&#x2F;caclient.rs#L62&quot;&gt;creates a CSR with the SPIFFE ID sending to Istiod over gRPC connection&lt;&#x2F;a&gt;, receiving response and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;identity&#x2F;auth.rs#L19&quot;&gt;verifying the certificate&lt;&#x2F;a&gt; and returning and storing complete &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;tls&#x2F;certificate.rs#L50&quot;&gt;Workload Certificate&lt;&#x2F;a&gt; used for mTLS :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------------------+       +-----------------------------------+       +---------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| Pod Alpha (Workload)   |       | ztunnel (on Pod Alpha&amp;#39;s Node)       |       | Istiod (Certificate Authority)  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|         (PA)           |       |                (ZT)               |       |                (ICA)            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------------------+       +-----------------------------------+       +---------------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       |                                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           | 1. Workload Starts Up                 |                                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           +---------------------------------------&amp;gt;| [ ZT activated ]                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | | 2. Determine Pod Alpha&amp;#39;s Identity   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |    (e.g., spiffe:&#x2F;&#x2F;cluster.local&#x2F;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |      ns&#x2F;default&#x2F;sa&#x2F;alpha)           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | | 3. Generate CSR &amp;amp; Private Key       | &#x2F;&#x2F; Note: CSR contains Pod Alpha&amp;#39;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |    for Pod Alpha                    | &#x2F;&#x2F; public key &amp;amp; desired identity (SAN)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | | 4. Send CSR to Istiod               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | +--------------------------------------&amp;gt;| [ ICA activated ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | | 5. Validate CSR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |    (Authenticate ztunnel,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |     check policies)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | | 6. Sign Certificate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |    (embedding Pod Alpha&amp;#39;s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |     identity)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | | 7. Send Signed Certificate back     | |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | +&amp;lt;--------------------------------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | [ ICA deactivated ]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | | 8. Store Certificate &amp;amp; Private Key  | &#x2F;&#x2F; Note: Certificate is now ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | |                                     | &#x2F;&#x2F; for mTLS handshakes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       | [ ZT deactivated ]                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;           |                                       |                                       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Requesting a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;identity&#x2F;manager.rs#L161&quot;&gt;certificate&lt;&#x2F;a&gt; from the CA for every connection would be very slow. So, ztunnel uses a SecretManager to efficiently manage and cache these certificates. The SecretManager and its supporting components:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Keeps track of certificates for all workloads on the node.&lt;&#x2F;li&gt;
&lt;li&gt;Handles requests to fetch certificates, possibly returning a cached one if it’s still valid.&lt;&#x2F;li&gt;
&lt;li&gt;Schedules background tasks to refresh certificates before they expire, ensuring workloads always have a valid certificate.&lt;&#x2F;li&gt;
&lt;li&gt;Manages the concurrency of requests to the CA to avoid overwhelming it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                    +------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                    | Certificate refresh    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                    | timer                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                    +------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                             |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                             v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Application        +----------------+              +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;makes request ---&amp;gt; | SecretManager  |    No       | Certificate     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  | Has valid      |------------&amp;gt; | needs refresh?   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  | cached cert?   |              +-----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  +----------------+                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  | Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      | Yes                              v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | Queue background |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | refresh          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | Worker checks    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | cert priority    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | Worker requests  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | cert from CA     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | CA validates and |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | returns cert     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | Store cert in    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         | cache           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |&amp;lt;------------------------|  Notify waiting  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      |                         |  applications    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                      v                         +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            | Return cached    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            | certificate      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            +------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each workload certificate is proactively refreshed halfway through its validity period, ensuring smooth operations without disruption due to expired certificates.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xds-client&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#xds-client&quot; aria-label=&quot;Anchor link for: xds-client&quot;&gt;xDS client&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Your service mesh is not static. New application versions get deployed (new workloads), old ones are removed, services scale up or down, and security policies change. ztunnel needs to know about all these changes in real-time to make correct routing and security decisions. How is stuff of ambient mesh updated in real time?&lt;&#x2F;p&gt;
&lt;p&gt;The XDS Client in ztunnel is the component responsible for communicating with Istiod to receive these dynamic configuration updates. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tetrate.io&#x2F;blog&#x2F;istio-service-mesh-delta-xds&#x2F;&quot;&gt;ztunnel uses a specific, efficient version of XDS called Delta ADS&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Aggregated&lt;&#x2F;em&gt;: Multiple types of information (like workloads, services, policies) are sent over a single connection, which is efficient.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Delta&lt;&#x2F;em&gt;: Instead of sending the entire configuration every time something small changes, Istiod only sends the differences (deltas – what’s new, what’s changed, what’s removed). This saves a lot of network traffic and processing time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state.rs#L1038&quot;&gt;xDS Client&lt;&#x2F;a&gt; connects to Istiod after checking &lt;code&gt;config.xds_address&lt;&#x2F;code&gt;, tells it what kind of information ztunnel is interested in, and then receives a stream of updates. These updates are then used to keep ztunnel’s internal Proxy State Management in sync.&lt;&#x2F;p&gt;
&lt;p&gt;Once connected, the &lt;code&gt;AdsClient&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds&#x2F;client.rs#L374&quot;&gt;sends initial DeltaDiscoveryRequest messages&lt;&#x2F;a&gt; to Istiod for each resource type it’s interested in (like ADDRESS_TYPE for workloads&#x2F;services and AUTHORIZATION_TYPE for policies). This request includes a Node identifier, which tells Istiod who this ztunnel is (e.g., its IP, pod name, namespace). This helps Istiod send relevant configuration. Istiod &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds&#x2F;client.rs#L682&quot;&gt;responds with DeltaDiscoveryResponse messages&lt;&#x2F;a&gt;. The first response usually contains the current state for the subscribed resources. Subsequent responses contain only the changes (deltas). The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds.rs#L105&quot;&gt;ProxyStateUpdater&lt;&#x2F;a&gt; receives the decoded XDS resources (e.g., XdsAddress which can be a workload or service, or XdsAuthorization for policies).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;proto&#x2F;xds.proto&quot;&gt;The xDS messages themselves are defined as Protocol Buffers (protobufs)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ztunnel (XDS Client)          Istiod (XDS Server)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |---------------------------→|  1. Establish Secure gRPC Connection (mTLS)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |     Uses workload ID       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |←---------------------------|  Connection Established&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |---------------------------→|  2. Send DeltaDiscoveryRequest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        | Subscribe to types         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |←---------------------------|  3. Send DeltaDiscoveryResponse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |    Initial mesh state      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |  Ongoing Updates Loop:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |←---------------------------|  4. Send DeltaDiscoveryResponse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |   Workload&#x2F;Policy updates  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |     &#x2F;-----------------\    |  5. Process updates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |     | Update internal |    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |     | ProxyState     |     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |     \-----------------&#x2F;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |---------------------------→|  6. Send ACK&#x2F;NACK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |    Update confirmation     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |  Loop continues...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |            ∙               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For very large meshes, ztunnel might not want to receive all configuration for all workloads and services upfront. So, there is an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds&#x2F;client.rs#L264&quot;&gt;on-demand XDS&lt;&#x2F;a&gt; feature which allows it to fetch only what it needs, when it needs it. The proxy state manager can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state.rs#L995&quot;&gt;request specific resources when it needs them&lt;&#x2F;a&gt;. The AdsClient &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds&#x2F;client.rs#L749&quot;&gt;listens for demand requests and sends them to Istiod&lt;&#x2F;a&gt;. When a response containing the requested resource arrives, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;xds&#x2F;client.rs#L234&quot;&gt;ztunnel notifies the waiting component&lt;&#x2F;a&gt;. Even if some resources in an update fail, the valid ones are still processed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;proxy-state-management&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#proxy-state-management&quot; aria-label=&quot;Anchor link for: proxy-state-management&quot;&gt;Proxy State Management&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The heart of ztunnel’s state management is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state.rs#L169&quot;&gt;ProxyState&lt;&#x2F;a&gt; which has specilized stores - records of all individual workloads, catalogs all the services, and archives all the security policies.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state&#x2F;workload.rs#L688&quot;&gt;WorklaodStore&lt;&#x2F;a&gt; is optimized for efficient lookups of Workloads. The store even optimizes for the common case where a single IP maps to a single workload. This structure provides multiple indices to find workloads efficiently by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;IP address + network&lt;&#x2F;li&gt;
&lt;li&gt;Unique identifier (UID)&lt;&#x2F;li&gt;
&lt;li&gt;Identity (for local workloads)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state&#x2F;service.rs#L332&quot;&gt;ServiceStore&lt;&#x2F;a&gt; manages information about Services. A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state&#x2F;service.rs#L37&quot;&gt;Service&lt;&#x2F;a&gt; is an abstraction for a group of workloads that together provide a certain functionality. Clients usually talk to a service’s stable virtual IP (VIP) and port, and the mesh routes the request to one of the healthy backing workloads. This structure allows for extremely fast lookups of services by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;VIP (Virtual IP address)&lt;&#x2F;li&gt;
&lt;li&gt;Hostname&lt;&#x2F;li&gt;
&lt;li&gt;Namespace + hostname combination&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;state&#x2F;policy.rs#L23&quot;&gt;PolicyStore&lt;&#x2F;a&gt; holds all the Authorization policies. These policies are the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;rbac.rs#L36&quot;&gt;RBAC rules&lt;&#x2F;a&gt; that dictate traffic flow. The policy store efficiently indexes policies by:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Full key (namespace&#x2F;name)&lt;&#x2F;li&gt;
&lt;li&gt;Namespace (for quickly finding all policies in a namespace)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It also includes a notification system to alert subscribers when policies change.&lt;&#x2F;p&gt;
&lt;p&gt;While ProxyState organizes the data efficiently, accessing it directly would be cumbersome for most operations. The DemandProxyState wrapper provides higher-level functionality and serves functions :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Concurrent access management: It safely handles the RwLock to ensure thread safety&lt;&#x2F;li&gt;
&lt;li&gt;On-demand resource fetching: It can request resources that aren’t in local cache&lt;&#x2F;li&gt;
&lt;li&gt;Metrics tracking: It maintains metrics about state operations&lt;&#x2F;li&gt;
&lt;li&gt;DNS resolution: It handles DNS lookups when needed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When an application pod (say, Pod A) sends a request to “Service B”, ztunnel (managing Pod A) intercepts this. So, the decision for routing happens :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   | Intercept      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   | request to     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   | Service B      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                          v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   | Look up        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   | Service B      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                   +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +---------------------+--------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                     |                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Found              Not                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v                   found                 v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +----------------+              |            +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Get healthy    |              |            | Try on-demand |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | endpoints      |              |            | fetch?        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +----------------+              |            +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                    |                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                    v                   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             +----------------+         | Yes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             | Request        |         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             | Service B      |&amp;lt;--------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             | from Istiod    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             +----------------+    No   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                    |              +----+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                    v              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             +----------------+    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             | Re-check       |    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             | ServiceStore   |    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |             +----------------+    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |                    |              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |            Found   |    Not found |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +--------------------+              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |                           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            v                           v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+         +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Select endpoint|         | Fail request   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Workload C     |         +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Look up        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Workload C     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Get IP, port,  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | protocol info  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    | Has waypoint?  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    +-------+-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                   Yes             No&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |               |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v               v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +----------------+ +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | Route through  | | Route directly |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         | waypoint       | | to Workload C  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         +----------------+ +----------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;dns-proxying&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#dns-proxying&quot; aria-label=&quot;Anchor link for: dns-proxying&quot;&gt;DNS Proxying&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;dns&#x2F;server.rs#L62&quot;&gt;DNS Proxying&lt;&#x2F;a&gt; in ztunnel is an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;proxyfactory.rs#L102&quot;&gt;optional feature&lt;&#x2F;a&gt; where ztunnel itself helps your applications (pods) find the IP addresses of other services. It acts as a local &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;dns&#x2F;server.rs#L332&quot;&gt;DNS resolver&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;dns&#x2F;server.rs#L831&quot;&gt;forwarder&lt;&#x2F;a&gt;. This speeds up lookups for services within the mesh because ztunnel can answer directly, and it ensures consistent name resolution.&lt;&#x2F;p&gt;
&lt;p&gt;When DNS Proxying is enabled:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Interception&lt;&#x2F;em&gt;: Network rules (often iptables) on the node are set up to redirect any DNS queries (on UDP port 53) sent by your local application pods to ztunnel’s DNS proxy listening port (e.g., 15053, configured by &lt;code&gt;config.dns_proxy_addr&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Local Resolution Attempt&lt;&#x2F;em&gt;: ztunnel receives the DNS query. It first checks if the requested name belongs to a service within the mesh using its internal Proxy State Management. If it’s a known mesh service (e.g., &lt;code&gt;checkout.default.svc.cluster.local&lt;&#x2F;code&gt;), ztunnel resolves it to the service’s Virtual IP (VIP) or endpoint IPs (for headless services). It then sends a DNS response directly back to the application pod. Queries for mesh services are resolved directly from the local state, avoiding network roundtrips, making it very fast.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Caching&lt;&#x2F;em&gt;: The DNS responses include appropriate TTLs to allow client-side caching.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Forwarding&lt;&#x2F;em&gt;: If ztunnel doesn’t know the name, it forwards the DNS query to the upstream DNS servers that are configured in its environment (typically &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;dns-pod-service&#x2F;&quot;&gt;kube-dns&lt;&#x2F;a&gt; or the node’s resolvers). If a service is not found in the mesh state, the query is seamlessly forwarded to upstream DNS.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Relaying Response&lt;&#x2F;em&gt;: When the upstream DNS server responds, ztunnel relays this response back to the application pod.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With the help of DNS proxying, we get :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Speed&lt;&#x2F;em&gt;: Resolving mesh-internal service names locally is much faster than going to an external DNS server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Accuracy&lt;&#x2F;em&gt;: ztunnel uses its live Proxy State Management data, ensuring that DNS results for mesh services reflect the current state of the mesh.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Consistency&lt;&#x2F;em&gt;: Helps ensure all pods get a consistent view of service addresses within the mesh.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Reduced Load on Upstream DNS&lt;&#x2F;em&gt;: Offloads queries for internal services from kube-dns or other central resolvers.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Enhanced Flexibility&lt;&#x2F;em&gt;: Supports both standard and headless services with appropriate IP addressing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;shutdown&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#shutdown&quot; aria-label=&quot;Anchor link for: shutdown&quot;&gt;Shutdown&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Ztunnel constantly listens for shutdown signals. This tells the DrainTrigger to notify all DrainWatchers and then waits for them to finish with their DrainMode.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;drain::new()&lt;&#x2F;code&gt; function creates the DrainTrigger and its initial DrainWatcher. This DrainWatcher can be cloned and passed to any component that needs to participate in the graceful shutdown.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;observibility&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#observibility&quot; aria-label=&quot;Anchor link for: observibility&quot;&gt;Observibility&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Good observability is crucial for any service mesh component, especially one handling production traffic like ztunnel. It provides comprehensive metrics across all its core functions - traffic proxying, DNS resolution, TLS certificate handling, and more, and integrate seamlessly into Prometheus, making them easy to visualize using tools like Grafana and setup AlertManager.&lt;&#x2F;p&gt;
&lt;p&gt;When ztunnel starts up, it creates a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;app.rs#L79&quot;&gt;central Prometheus registry that will hold all metrics&lt;&#x2F;a&gt;. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;metrics.rs#L33&quot;&gt;metrics::sub_registry()&lt;&#x2F;a&gt; function creates a namespace for Istio-specific metrics to avoid conflicts with other systems. Each component (Proxy, DNS, XDS, etc.) defines its own metrics in a dedicated module. For connection-oriented operations like proxying traffic, ztunnel uses a pattern where metrics are incremented at the start of an operation and then finalized when the operation completes.&lt;&#x2F;p&gt;
&lt;p&gt;Ztunnel &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel?tab=readme-ov-file#metrics&quot;&gt;exposes its metrics through an HTTP endpoint in the Prometheus format&lt;&#x2F;a&gt; with a rich set of labels which allows you to filter and group metrics by workload, namespace, service, security policy, and more, allowing bifurcation like :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Identifying which services generate the most traffic&lt;&#x2F;li&gt;
&lt;li&gt;Spotting security policy violations&lt;&#x2F;li&gt;
&lt;li&gt;Tracking error rates between specific service pairs&lt;&#x2F;li&gt;
&lt;li&gt;Monitoring the performance impact of mesh configuration changes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are access logs for detailed event tracking as well.
It’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;master&#x2F;PROFILING.md&quot;&gt;profiled&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;tree&#x2F;master&#x2F;benches&quot;&gt;benchmarked extensively&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-rusty-aspect-of-ztunnel&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-rusty-aspect-of-ztunnel&quot; aria-label=&quot;Anchor link for: the-rusty-aspect-of-ztunnel&quot;&gt;The Rusty aspect of Ztunnel&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;S39yo6ZJ4iM?si=WZinWe_2riCilu4y&quot;&gt;Istio’s Ambient Mesh was specifically designed for Scalability&lt;&#x2F;a&gt;. But Rust is not the reason Ztunnel is scalable.&lt;&#x2F;p&gt;
&lt;p&gt;You won’t believe me, but the creator of ztunnel wrote it in Go, but was not satisfied with the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;benches&#x2F;README.md&quot;&gt;performance&lt;&#x2F;a&gt;, renamed all the files to &lt;code&gt;.rs&lt;&#x2F;code&gt; and with the help of the Rust compiler did a complete rewrite in Rust (◕▽◕) Crazyyyyy…&lt;&#x2F;p&gt;
&lt;p&gt;Ztunnel boasts a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;users.rust-lang.org&#x2F;t&#x2F;one-or-multiple-runtimes-for-tokio-webserver&#x2F;110149&quot;&gt;dual runtime&lt;&#x2F;a&gt; model :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Control Plane Runtime is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;main.rs#L46&quot;&gt;main thread&lt;&#x2F;a&gt; which handles tasks that are essential for the proxy’s management and configuration but are not directly impacting the data plane. It includes xDS client fetching configuration updates from Istiod, debug interfaces and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;app.rs#L220&quot;&gt;health checks&lt;&#x2F;a&gt; impacting the data plane. As the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;app.rs#L111&quot;&gt;Admin tasks&lt;&#x2F;a&gt; are often sequential or don’t require high parallelism and requires less resources that could otherwise be used for data plane tasks, a single thread is easier to reason about and debug. Crucially, if something goes wrong in an admin task (e.g., a bug in xDS handling, a panic in a debug endpoint), it’s less likely to crash or stall the entire data plane that’s handling live user traffic. The user request flow remains unaffected.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Data Plane Runtime have the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;istio&#x2F;ztunnel&#x2F;blob&#x2F;46acf764633bb109037cc231670dd5df74a50219&#x2F;src&#x2F;app.rs#L239&quot;&gt;worker threads&lt;&#x2F;a&gt; which handles the actual user traffic. This is the high-performance low-latency multi-thread Tokio runtime route to handle users requests which includes accepting incoming client connections, processing request headers&#x2F;data, applying policies (load balancing, retries, timeouts, security), establishing outgoing connections to upstream services (this is where the “connection pool” comes in), forwarding data between client and server. The worker thread count (defaults to 2) is configurable based on the expected load and available hardware resources, common starting point often being the number of CPU cores spreading the load of encrypting&#x2F;decrypting traffic, parsing, and other request processing tasks across multiple CPU cores. Tokio’s multi-threaded runtime can efficiently manage many concurrent connections across a few OS threads by leveraging non-blocking I&#x2F;O. This allows ztunnel to handle a high volume of requests simultaneously.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Ideally, these two runtimes operate largely independently. This separation is a robust design. The admin runtime can be busy fetching a large xDS update, or even hang momentarily, without directly stalling the forwarding of packets on the worker threads.&lt;&#x2F;p&gt;
&lt;p&gt;The connection pool is managed by worker threads. When establishing connection it consults the current configuration (provided by the admin runtime) to know where to connect, thus this configuration needs to be made available to the worker threads in a thread-safe way, done using mpsc channel.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I urge folks who are interested to go through the ztunnel codebase and contribute to the project, its really well designed, and too big to cover in a single blog. A lot of things to learn from the codebase.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t forget to Star it as well! Though I have covered a lot of technical aspects in here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;grateful&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#grateful&quot; aria-label=&quot;Anchor link for: grateful&quot;&gt;Grateful&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I am more than grateful to the wonderful folks at Solo.io who mentored me - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ilrudie&quot;&gt;Ian Rudie&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;howardjohn&quot;&gt;John Howard&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bleggett&quot;&gt;Ben Leggett&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kfaseela&quot;&gt;Faseela K&lt;&#x2F;a&gt;.
Forever grateful to them for volunteering their time and effort.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Do I officially qualify as a Software Engineer now?</title>
          <pubDate>Mon, 13 Jan 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/do-i-officially-qualify-as-a-software-engineer/</link>
          <guid>https://harsh-ps-2003.github.io/writes/do-i-officially-qualify-as-a-software-engineer/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/do-i-officially-qualify-as-a-software-engineer/">&lt;p&gt;With another internship coming to end, I officially have around 1 year systems programming experience (internship experience tbh) and I am quite sad, because I still don’t seem to have much knowledge ( ͡° ʖ̯ ͡°)
or I am just working with extremely smart people, who knows?&lt;&#x2F;p&gt;
&lt;p&gt;I am really thinking of pursuing research in Computational Sciences. Confused… To many lucrative options.&lt;&#x2F;p&gt;
&lt;p&gt;This writeup is how I am thinking of writing my Rust applications from now on.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-s-not-your-personal-project&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-s-not-your-personal-project&quot; aria-label=&quot;Anchor link for: it-s-not-your-personal-project&quot;&gt;It’s not your personal project…&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Well, production software has to be written keeping the conventional wisdom in mind, i.e. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-unofficial.github.io&#x2F;patterns&#x2F;additional_resources&#x2F;design-principles.html#a-brief-overview-over-common-design-principles&quot;&gt;Design Principles&lt;&#x2F;a&gt; along with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-unofficial.github.io&#x2F;patterns&#x2F;patterns&#x2F;index.html&quot;&gt;Design Patterns&lt;&#x2F;a&gt;. When creating a simple personal project, I never took care of using abstraction much, but I saw the senior engineers using it quite a lot. I still am not a fan of unnecessary abstractions tbh. And I like things stupid-simple. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;boston.conman.org&#x2F;2004&#x2F;10&#x2F;19.1&quot;&gt;I was very procedural when I started out, and now I look at OOPs as an organizational principle&lt;&#x2F;a&gt;. But don’t get on horses with proc-macro and trait magic to the point that the code is bloody incomprehensible and extremely difficult to debug.&lt;&#x2F;p&gt;
&lt;p&gt;My focus is to make the code low-latency and performant, easy to traverse by new-comers i.e. very debuggable, maintainable and makes future migrations easy-peeasy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;And, No over-engineering!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wisdom-of-programming-sages&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wisdom-of-programming-sages&quot; aria-label=&quot;Anchor link for: wisdom-of-programming-sages&quot;&gt;Wisdom of programming sages&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I think of a hybrid of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.howtocodeit.com&#x2F;articles&#x2F;master-hexagonal-architecture-rust&quot;&gt;Hexagonal Architecture&lt;&#x2F;a&gt; and Actor Model, keeping in mind the Dependency Inversion priciple as Uncle Bob calls it - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=N5rZZbBGrQ4&quot;&gt;Clean Architecture&lt;&#x2F;a&gt; and closely following &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.dataorienteddesign.com&#x2F;dodbook&#x2F;node2.html&quot;&gt;Data-oriented approach&lt;&#x2F;a&gt;. I don’t feel happy as a traditional OOPs guy! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jeffreypalermo.com&#x2F;2008&#x2F;07&#x2F;the-onion-architecture-part-1&#x2F;&quot;&gt;Onion Architecture&lt;&#x2F;a&gt; also shares similar principles, but was originally limited to OOPs.&lt;&#x2F;p&gt;
&lt;p&gt;I ofcourse use objects, inheritance and all, but I despise debugging a enterprise OOPs codebase, just going through classes and classes, and those never ending classes. I favor composition over inheritance to avoid inheritance spaghetti, i.e. unexpected coupling of system components.&lt;&#x2F;p&gt;
&lt;p&gt;Hahhh…. the I need to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;~wcook&#x2F;Drafts&#x2F;2009&#x2F;essay.pdf&quot;&gt;understand Data Abstractions&lt;&#x2F;a&gt; and overall &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;paradigms&#x2F;&quot;&gt;Programming Paradigms in Rust&lt;&#x2F;a&gt; better&lt;&#x2F;p&gt;
&lt;h3 id=&quot;trancending-oops&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#trancending-oops&quot; aria-label=&quot;Anchor link for: trancending-oops&quot;&gt;Trancending OOPs&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Yes, I maintain a plugin in Jenkins, which is completely based on traditional JAVA and its OOPs concepts. But, when writing performant software in Rust, I don’t think OOPs is the best thing. Or maybe it’s just me who doesn’t like Abstract Classes which encourage tight coupling and hinder cache alignment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.&lt;&#x2F;em&gt; – Joe Armstrong, the creator of Erlang&lt;&#x2F;p&gt;
&lt;p&gt;In OOPs, there are layers and layers of abstractions, and logic deep within. It almost promotes complexity ( ͠° ͟ʖ ͡°), I like things simple.
Deep hierarchies often lead to derived classes depending on sibling classes through shared base class behavior. This interdependence makes it harder to refactor or optimize parts of the system independently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wiki.c2.com&#x2F;?ArgumentsAgainstOop&quot;&gt;There are plenty of arguments against OOPs&lt;&#x2F;a&gt;, but still, OOPs is undeniably and rightfully so, a really reliable guiding principle.&lt;&#x2F;p&gt;
&lt;p&gt;Poorly designed inheritance hierarchies lead to fragility and coupling, paired with overengineering (e.g., excessive patterns) detracts from solving actual problems. The developer overly focus on &lt;em&gt;code instead of data&lt;&#x2F;em&gt; which shouldn’t be the case.&lt;&#x2F;p&gt;
&lt;p&gt;I am learning about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=rX0ItVEVjHc&quot;&gt;Data-oriented design&lt;&#x2F;a&gt; which avoids complex reference graphs by storing data in flat, database-like structures, where the relationships are ID-based, avoiding circular referencing, and access patterns are simple.&lt;&#x2F;p&gt;
&lt;p&gt;I guess, the best way forward to mingle both OOPs and DoD, combining DoD’s efficiency with OOP’s modularity. I fear over-engineering, don’t wanna fall into that trap! And DoD just feels less natural for me for some reason.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hybrid-architecture-of-my-dreams&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hybrid-architecture-of-my-dreams&quot; aria-label=&quot;Anchor link for: hybrid-architecture-of-my-dreams&quot;&gt;Hybrid Architecture of my dreams…&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The essence is that my core business logic should be ignorant about the rest of the system. External things like API, DB, cache, filesystem, etc, should be abstracted by interfaces. Interfaces make interactions of my applications with the outside world well described and structured. Also, I can simply test these interface implementations.&lt;&#x2F;p&gt;
&lt;p&gt;But I want good abstractions, not layers and layers of code. What abstractions should achieve is they should help me reason about the solution in simpler terms. In essence they should allow me to think about problem from a birds eye view. It’s really not easy to create a abstraction most often we just add layers of functions not abstractions. Good abstraction decoupled low level thinking and high level thinking.&lt;&#x2F;p&gt;
&lt;p&gt;[Each actor is like a small little application, self-contained, capable of performing its tasks (often as multiple spawned threads - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blaz.is&#x2F;blog&#x2F;post&#x2F;lets-pretend-that-task-equals-thread&#x2F;&quot;&gt;task is not a thread&lt;&#x2F;a&gt;) and interacting with other actors through channels](https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fTXuGRP1ee4), mpsc or broadcast or watch, just &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.digital-horror.com&#x2F;blog&#x2F;how-to-avoid-over-reliance-on-mpsc&#x2F;&quot;&gt;avoid over-relying on mpsc&lt;&#x2F;a&gt;, and can be run and tested seperately using mock channels. &lt;em&gt;Actors communicate by sending messages rather than sharing memory.&lt;&#x2F;em&gt; The main application code is then just an actor coordinator - setting-up main actors, gluing them together with channels, starting them, then detecting exit conditions and&#x2F;or critical failures and coordinating &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;tokio&#x2F;topics&#x2F;shutdown&quot;&gt;shutdown&lt;&#x2F;a&gt;, etc. This model is particularly powerful in building concurrent, distributed, and fault-tolerant systems, which I was generally involved in building during my internships. Managing a shared I&#x2F;O resource is just better with actors. I just create a &lt;code&gt;Spawn&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;reference&#x2F;procedural-macros.html&quot;&gt;proc-macro&lt;&#x2F;a&gt; for generating spawn methods for actor structs, consistent cancellation via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;tokio&#x2F;topics&#x2F;shutdown&quot;&gt;CancellationToken for graceful shutdown&lt;&#x2F;a&gt; and uniform tracing and error handling. I love Rust macros! But &lt;code&gt;tracing::instrument&lt;&#x2F;code&gt; in particular is slow! Use &lt;code&gt;derive_builder&lt;&#x2F;code&gt; and the verbose stuct builder boilerplate is gone. My favourite &lt;code&gt;tonic&lt;&#x2F;code&gt; uses macros for gRPC. And, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;immutability&#x2F;&quot;&gt;I generally aim for immutability.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The hexagonal architecture is stupid simple not only because it makes the codebase modular, but also because it allows me to defer some decisions to a later stage in the development of a system.&lt;&#x2F;p&gt;
&lt;p&gt;Btw, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;quickwit.io&#x2F;blog&#x2F;quickwit-actor-framework#using-the-actor-framework-in-quickwit&quot;&gt;Quickwit uses the actor model really well!&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@evadawnley&#x2F;leveraging-rusts-tokio-library-for-asynchronous-actor-model-cf6d477afb19&quot;&gt;this blog&lt;&#x2F;a&gt; is a very easy to follow actor model implementation.&lt;&#x2F;p&gt;
&lt;p&gt;Hilariously, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pingcap.com&#x2F;blog&#x2F;rust-huge-compilation-units&#x2F;&quot;&gt;Rust compiles fast software slowly!&lt;&#x2F;a&gt; In Rust, each crate is a compilation unit (not file like in C++) either compiling into a binary &lt;code&gt;bin&lt;&#x2F;code&gt; or library &lt;code&gt;rlib&lt;&#x2F;code&gt;, which is good as it eases global optimization across modules, and is just better! When any module in a crate is changed, the crate is recompiled, pushing us to have multiple small crates instead of a large slow crate. So, I need to think about my dependency spaghetti, avoiding as many inter-dependencies as I can and arrange the crate dependencies such that as much of my workspace can be can benefit from parallel compilation. And, I need to use my intuition to keep the ever-changing code as outside the spaghetti, as I don’t want to recompile the whole damn thing just after a simple tweak. Sometimes, just introduce an extra &lt;code&gt;Arc&amp;lt;dyn Trait&amp;gt;&lt;&#x2F;code&gt; somewhere just to decouple two things and avoid dependency between them, instead of both of them depending on a common interface (which changes much less frequently). I recently found about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rui314&#x2F;mold&quot;&gt;mold, a high-performance linker&lt;&#x2F;a&gt;, which is a absolute heart-throb! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;tips-for-faster-rust-compile-times&#x2F;&quot;&gt;Who won’t appreciate faster compile time in Rust?&lt;&#x2F;a&gt; Well, we can &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;09&#x2F;04&#x2F;fast-rust-builds.html&quot;&gt;tweak the configs for faster Rust builds&lt;&#x2F;a&gt;, though they can be fragile.&lt;&#x2F;p&gt;
&lt;p&gt;One more thing to consider is that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.uffizzi.com&#x2F;blog&#x2F;optimizing-rust-builds-for-faster-github-actions-pipelines&quot;&gt;CI&#x2F;CD should prioritize speed and relibility otherwise its bad for developer productivity&lt;&#x2F;a&gt;. The default dev profile enables debug symbols, slowing down CI builds, and the default release profile optimizes for runtime speed, but CI might need faster compilation instead. So using a custom build profile is just better! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Swatinem&#x2F;rust-cache&quot;&gt;Cache the CI smartly&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;ci&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;inherits&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;release&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; # &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Inherit&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; release&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; level&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;        # &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Debugging&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; not&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; required&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; binary&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;lto&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;          # &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Disable&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Link&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Optimization&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; it&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; slows&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; linking&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; down&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;codegen&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;units&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;   # &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Increase&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parallelism&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; faster&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; compilation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;incremental&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;  # &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Disable&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; incremental&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; compilation&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; clean&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; builds&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ensuring&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; consistency&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;but when you want to release the optimized binary :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;profile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;release&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;lto&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;tips-for-faster-ci-builds&#x2F;&quot;&gt;Faster CI builds in Rust significantly improve developer velocity.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;match-made-in-heaven&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#match-made-in-heaven&quot; aria-label=&quot;Anchor link for: match-made-in-heaven&quot;&gt;Match made in Heaven&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Rust is not exactly an OOP language.&lt;&#x2F;em&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cs.smu.ca&#x2F;~porter&#x2F;csc&#x2F;common_341_342&#x2F;notes&#x2F;oop_3pillars.html&quot;&gt;Rust does not support inheritance&lt;&#x2F;a&gt; and its trait system is modular by design.&lt;&#x2F;p&gt;
&lt;p&gt;I am genuienly wondering, how Rust is gaining popularity regardless of the fact that its not OOPs-centric, just like OOPs at surface (゜ロ゜). Its amazing! Maybe because it’s a general-purpose language, so you can build backends, CLIs, GUIs, and ofcourse embedded firmware. Also, cargo is just the best build+package manager that I have ever used. And also a feeling that Rust makes you confident about your program.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5QFDQRkbllo&quot;&gt;Traits are like interfaces in Java&lt;&#x2F;a&gt;, but is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5oUOc6vDRtc&quot;&gt;inspired by Haskell’s&lt;&#x2F;a&gt; typeclass. Literally, traits + generics + lifetimes, and the chef’s kiss!!! Code-sample because I am proud of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;lifetimes&#x2F;&quot;&gt;understanding lifetimes&lt;&#x2F;a&gt;, atleast naively :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cmp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Ordering&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Trait holding two references with distinct lifetimes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Comparator&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; compare&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordering&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; By separating these lifetimes, Rust ensures that the struct&amp;#39;s &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; validity depends on the shorter of the two lifetimes.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Comparison&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Comparator&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Comparison&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ord&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; compare&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ordering&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cmp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;right&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; A function that takes a &amp;#39;static reference&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; static_comparator&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; other&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ord&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Simply returns the `&amp;#39;static` reference as it outlives the other&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Long-lived data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; long_lived&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, Rust!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Short-lived data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; short_lived&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Comparison of references with different lifetimes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; comparison&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Comparison&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;long_lived&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;short_lived&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Comparison result: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            comparison&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;compare&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Greater&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Demonstrating `&amp;#39;static` usage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; static_str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Static reference&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; static_comparator&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;static_str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;long_lived&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Result from static comparator: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; result&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just adding one confusion that I faced when working on a personal project and how I solved it :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;chord_handle&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; actor&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ChordHandle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;node_id&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; port&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; addr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Spawn the actor and store its handle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; actor_handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tokio&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            actor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; returns a future which borrowed actor rather than owning it so move captures the actor and moves ownership to the spawned task&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;when I was directly trying to spawn the actor &lt;code&gt;tokio::spawn(actor.run());&lt;&#x2F;code&gt; I was getting a static lifetime issue! I went through the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;task&#x2F;fn.spawn.html&quot;&gt;tokio’s docs&lt;&#x2F;a&gt; and found &lt;code&gt;There is no guarantee that a spawned task will execute to completion. When a runtime is shutdown, all outstanding tasks are dropped, regardless of the lifecycle of that task.&lt;&#x2F;code&gt;. Now, in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;thread&#x2F;fn.spawn.html&quot;&gt;std::spawn() docs&lt;&#x2F;a&gt; its mentioned &lt;code&gt;The &#x27;static constraint means that the closure and its return value must have a lifetime of the whole program execution. The reason for this is that threads can outlive the lifetime they have been created in.&lt;&#x2F;code&gt;. So the &lt;code&gt;&#x27;static&lt;&#x2F;code&gt; can outlive the lifetime &lt;code&gt;&#x27;a&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 42&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    tokio&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ❌ ERROR: `x` does not have a `&amp;#39;static` lifetime&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;x&lt;&#x2F;code&gt; is allocated on the stack of &lt;code&gt;main()&lt;&#x2F;code&gt;, but the spawned thread may continue running after &lt;code&gt;main()&lt;&#x2F;code&gt; exits.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 42&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    tokio&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ Move `x` into the async block&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using move, we ensure the closure takes ownership of &lt;code&gt;x&lt;&#x2F;code&gt;, making sure it is available for the spawned thread.&lt;&#x2F;p&gt;
&lt;p&gt;To avoid all this, we can simply use &lt;code&gt;crossbeam::scope&lt;&#x2F;code&gt; which creates a temporary scope where threads are spawned.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;scope&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; x&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ Works fine, as `x` is guaranteed to live&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Scope ensures all threads finish before exiting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since the scope will make sure that all threads are joined before the scope ends, the closures don’t need to be &lt;code&gt;&#x27;static&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I cant emphasize on the fact how helpful the Rust compiler is. Once you be-friend the borrow checker, you are sorted.&lt;&#x2F;p&gt;
&lt;p&gt;I use Tokio’s &lt;code&gt;JoinSet&lt;&#x2F;code&gt; for task lifecycle management and &lt;code&gt;Arc&amp;lt;RwLock&amp;lt;T&amp;gt;&amp;gt;&lt;&#x2F;code&gt; for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;tokio&#x2F;tutorial&#x2F;shared-state&quot;&gt;thread-safe shared state&lt;&#x2F;a&gt;. Futures are lazy by default, so they don’t do any work until they’re polled. This allows for patterns where computations are delayed until they’re actually needed. Also, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;55552413&#x2F;what-is-the-difference-between-then-and-then-and-or-else-in-rust-futures&quot;&gt;callback chains are easy using &lt;code&gt;then&lt;&#x2F;code&gt;, &lt;code&gt;and_then&lt;&#x2F;code&gt; and &lt;code&gt;or_else&lt;&#x2F;code&gt;.&lt;&#x2F;a&gt; I can simply use &lt;code&gt;join!&lt;&#x2F;code&gt; macro to await multiple futures concurrently, and &lt;code&gt;join_all()&lt;&#x2F;code&gt; for fan-out, fan-in patterns.&lt;&#x2F;p&gt;
&lt;p&gt;I personally like using type-alias instead of raw primitive types. Just makes the code so much more readable. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;illegal-state&#x2F;&quot;&gt;I like using custom types to model my domain.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ianlewis.org&#x2F;en&#x2F;rust-first-impressions-error-handling&quot;&gt;Error handling in Rust is just gorgeous&lt;&#x2F;a&gt;. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;rust-option-handling-best-practices&#x2F;&quot;&gt;And stop using unwraps all around the place!&lt;&#x2F;a&gt;. Just throw the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@vennilapugazhenthi&#x2F;what-does-the-question-mark-operator-do-in-rust-581fe7bc4b0e&quot;&gt;&lt;code&gt;?&lt;&#x2F;code&gt; operator&lt;&#x2F;a&gt; all around the place.&lt;&#x2F;p&gt;
&lt;p&gt;When I heard about Rust, &lt;em&gt;fearless concurrency&lt;&#x2F;em&gt; was something I kept on hearing about. And stupid me thought I don’t have to worry about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redixhumayun.github.io&#x2F;concurrency&#x2F;2024&#x2F;05&#x2F;17&#x2F;data-race-vs-race-condition.html&quot;&gt;race conditions and deadlocks when using Rust&lt;&#x2F;a&gt; at all now (◞‿◟)&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.dev&#x2F;blog&#x2F;2024&#x2F;03&#x2F;21&#x2F;testing-in-rust#rust-testing-library-crates&quot;&gt;fixtures and paramatrization when testing&lt;&#x2F;a&gt; a lot these days when &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lpalmieri.com&#x2F;posts&#x2F;an-introduction-to-property-based-testing-in-rust&#x2F;&quot;&gt;writing property-based tests&lt;&#x2F;a&gt;. Also, for similar test cases, I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;test-case&#x2F;latest&#x2F;test_case&#x2F;&quot;&gt;test_case&lt;&#x2F;a&gt; procedural macro for generating parameterized tests and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;proptest-rs.github.io&#x2F;proptest&#x2F;intro.html&quot;&gt;PropTest&lt;&#x2F;a&gt; for generating property tests. And ofcourse &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;05&#x2F;31&#x2F;how-to-test.html&quot;&gt;follow general rust testing&lt;&#x2F;a&gt; and its &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;2021&#x2F;02&#x2F;27&#x2F;delete-cargo-integration-tests.html&quot;&gt;organizational&lt;&#x2F;a&gt; guidelines. Also, I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RazrFalcon&#x2F;cargo-bloat&quot;&gt;cargo-bloat&lt;&#x2F;a&gt; for size profiling my binaries.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;async-await-internals&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#async-await-internals&quot; aria-label=&quot;Anchor link for: async-await-internals&quot;&gt;async&#x2F;await internals&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;OS threads are never going to be fast. Rust chose Stackless coroutines which added complexity to semantics but improved performance, compared to Green threads which give same semantics as OS level threads but is a downgrade on performance as now a runtime scheduler to do &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kerkour.com&#x2F;cooperative-vs-preemptive-scheduling&quot;&gt;preemptive multitasking&lt;&#x2F;a&gt;. Async + Lifetime is surely hard to wrap your head around.&lt;&#x2F;p&gt;
&lt;p&gt;In Rust, the async&#x2F;await model turns the async block into a state machine. Each await point can cause the future to be paused and resumed later, possibly on a different thread. Futures are self-contained concurrent execution units, just like threads to multi-cores. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;emschwartz.me&#x2F;pinning-down-future-is-not-send-errors&#x2F;&quot;&gt;If you spawn a Future it must be &lt;code&gt;Send + Sync + &#x27;static&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. For the future to be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;marker&#x2F;trait.Send.html&quot;&gt;Send&lt;&#x2F;a&gt;, all the data it holds across await points must also be Send. Having a non-Send type in Future is okay (just means you can only execute it in a single-threaded runtime), but holding it across await is not! Each &lt;code&gt;.await&lt;&#x2F;code&gt; introduces a new state (while it waits for something) and the code in between are state transitions (a.k.a tasks), which will be triggered based on some external event (e.g. from IO or a timer etc). Something like &lt;code&gt;Rc&lt;&#x2F;code&gt; is not Send, since cloning&#x2F;dropping in two different threads can cause the reference count to get out of sync, so it can’t be sent among threads. Each task gets scheduled to be executed by the async runtime, which could choose to use a different thread from the previous task. If the state transition is not safe to be sent between threads then the resulting Future is also not Send so that you get a compilation error if you try to execute it in a multi-threaded runtime. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;emschwartz.me&#x2F;async-rust-can-be-a-pleasure-to-work-with-without-send-sync-static&#x2F;&quot;&gt;Async Rust is certainly a pleasure to work with&lt;&#x2F;a&gt; ◴_◶&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ryhl.io&#x2F;blog&#x2F;async-what-is-blocking&#x2F;&quot;&gt;Async code should never spend a long time without reaching an .await.&lt;&#x2F;a&gt; until you wanna block the thread. The primary difference between what Go does and what async Rust does is whether the scheduling is preemptive or cooperative. In async Rust, your runtime will swap out the currently running task on each worker thread whenever it reaches an .await and has to wait for IO or something, but the swap can only happen at an .await. In Go, this is different, the scheduling is preemptive, which means that a task can be swapped at any time. In Go, everything is implicitly async, which is not the case with Rust. If your &lt;code&gt;main()&lt;&#x2F;code&gt; function is not marked with &lt;code&gt;#[tokio::main]&lt;&#x2F;code&gt;, it is synchronous by default in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tokio.rs&#x2F;blog&#x2F;2019-10-scheduler&quot;&gt;tokio’s rewrite PR&lt;&#x2F;a&gt; made the scheduler really good! I was already a &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www1.cs.columbia.edu&#x2F;~aho&#x2F;cs6998&#x2F;reports&#x2F;12-12-11_DeshpandeSponslerWeiss_GO.pdf&quot;&gt;fan of Go’s unique runtime scheduler&lt;&#x2F;a&gt; due to it’s combination of features like very small stacks for creating a very large number of goroutines, Colorless functions, built-in, runs without VM, integrated with garbage collector, stackful, etc. Rust did start with an M:N, work-stealing scheduler based on stackful coroutines, but was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rfcs&#x2F;blob&#x2F;master&#x2F;text&#x2F;0230-remove-runtime.md&quot;&gt;removed from the std lib&lt;&#x2F;a&gt;. The groundbreaking thing that Go did is to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;talks&#x2F;2012&#x2F;splash.article#TOC_13.&quot;&gt;optimize the entire language for highly concurrent I&#x2F;O-bound workloads&lt;&#x2F;a&gt;, but Rust is strictly more performant than Go. It’s using state-machine based stackless coroutines, which emulate the way that manual asynchronous implementations like Nginx. You can’t get more efficient than this along with the fact that Rust doesn’t have a GC and features more aggressive compiler optimizations.&lt;&#x2F;p&gt;
&lt;p&gt;Recently I was working on a personal project, and got really confused on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hegdenu.net&#x2F;posts&#x2F;understanding-async-await-3&#x2F;&quot;&gt;why even after dropping the &lt;code&gt;MutexGuard&lt;&#x2F;code&gt; I can’t hold it across await!&lt;&#x2F;a&gt; (◎＿◎;)
So, the issue is that the compiler can’t always track that the &lt;code&gt;MutexGuard&lt;&#x2F;code&gt; is no longer present after the drop. The compiler’s analysis of what lives across await points is conservative. The state machine might still include it in its captured variables, making the future non-Send. Using blocks instead of &lt;code&gt;drop()&lt;&#x2F;code&gt; is better practice because it ensures all variables in the scope are dropped, not just the ones you remember. This helps prevent similar issues and keeps the future’s state smaller.&lt;&#x2F;p&gt;
&lt;p&gt;So yeah, understanding these yada yada stuff is important.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-custom-macros-seems-problematic&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-custom-macros-seems-problematic&quot; aria-label=&quot;Anchor link for: the-custom-macros-seems-problematic&quot;&gt;The custom macros seems problematic&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Custom derives generates implementations for traits like &lt;code&gt;Serialize&lt;&#x2F;code&gt; at the location of the struct definition. This ties the core domain models to serialization concerns. If I want the core to be independent of external dependencies (e.g., serde), adding such derives will violate the principle of modularity. And, Rust’s orphan rules prevent trait implementations in separate modules or crates unless either the trait or the type is local, further complicating separation of concerns. A quite normal pattern I’ve seen done by many crates is to make a feature for &lt;code&gt;serde&lt;&#x2F;code&gt; and then only derive the implementation if the feature is enabled. This means that all crates which need &lt;code&gt;serde&lt;&#x2F;code&gt; can enable it, but all crates which don’t can just leave the feature off.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I think that serialization code is in general tightly coupled to the actual underlying data, hence it makes a lot of sense that it’s implemented directly next to the data, if situation allows it. &lt;em&gt;Dependencies that set the vocabulary for other crates should be allowed into the core.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Maybe there needs to be a Rust-adjusted sort of a Hexagonal Architecture, where the core knows that there is some logging, some database and some user interfaces, but does not choose specific technology? Like depending on &lt;code&gt;log&lt;&#x2F;code&gt;, &lt;code&gt;serde_derive&lt;&#x2F;code&gt; and some UI abstraction crate implementable by &lt;code&gt;clap&lt;&#x2F;code&gt;; but not on &lt;code&gt;env_logger&lt;&#x2F;code&gt;, &lt;code&gt;serde_json&lt;&#x2F;code&gt; or &lt;code&gt;clap&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The core has to be built around the business model, which could evolve at leisure, be sliced and diced, or fused, and was entirely unaware of the messages&#x2F;protocols involved in the outer I&#x2F;O layers. A distributed application requires the ability to support multiple versions of the messages that are exchanged, and sometimes to radically switch the protocol to support new functionality, while supporting previous versions so that clients can migrate incrementally.&lt;&#x2F;p&gt;
&lt;p&gt;When I serialize my core business model, I lose encapsulation (struct represents a coherent piece of the domain logic, and all its internal details are private or controlled by its API (e.g., methods) and the other parts of my application shouldn’t directly manipulate this structure or depend on its exact representation), which seriously affects my ability to evolve communications.&lt;&#x2F;p&gt;
&lt;p&gt;Serialization exposes the internal representation of your core business model because it directly maps fields into a specific format (e.g., JSON, Protobuf), tying them together. The serialized format (e.g., JSON keys) is a 1-to-1 mapping of the fields in the struct (id, name, email). If you change the field names or types, you break compatibility with anything consuming this serialized data.&lt;&#x2F;p&gt;
&lt;p&gt;In distributed systems, serialized data often persists in storage or is sent between systems. Changing the format can be costly or impossible without breaking clients. Using Data Transfer Object, we can add a layer of indirection. A shallow mapping between the core and the serialized representation protects your system’s modularity and flexibility. Though this is expensive, but might be good for long-term projects.&lt;&#x2F;p&gt;
&lt;p&gt;Well, depending upon the complexity, this can quickly get tedious, confusing and also error prone as the project grows. So, I don’t know how to go about this :(&lt;&#x2F;p&gt;
&lt;p&gt;Rust’s zero-cost abstractions enable the creation of lightweight wrapper types (e.g. Http&lt;T&gt;) or thin adapters without runtime overhead. So we can have a local impl in our crate for the generic as well, and serialize that.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;but-i-don-t-do-anything-from-the-get-go&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#but-i-don-t-do-anything-from-the-get-go&quot; aria-label=&quot;Anchor link for: but-i-don-t-do-anything-from-the-get-go&quot;&gt;But I don’t do anything from the get go..&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Yup, still when I write code, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=DsAclZbP_Us&quot;&gt;I want the architecture to grow organically so that I don’t end up with Clean Code and Bad Performance&lt;&#x2F;a&gt;. &lt;em&gt;I don’t paste solutions to problems.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It’s stupid, but guess what I am not even a Junior Engineer right now, so I am somewhat allowed to be stupid. I avoid &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code-smells.com&#x2F;dispensables&#x2F;speculative-generality&quot;&gt;Speculative Generality&lt;&#x2F;a&gt;. My general workflow is, get this running -&amp;gt; make it better -&amp;gt; refactor -&amp;gt; repeat. If any clean&#x2F;hexagonal architecture is required, only then go ahead, otherwise I only care about solving the problem at hand, not the code mumbo-jumbo.&lt;&#x2F;p&gt;
&lt;p&gt;I am just thinking about these design decisions these days, and will try incorporating this in my next personal project to get a feel of these things! Oh! and I feel very happy when I see &lt;code&gt;ARCHITECTURE.md&lt;&#x2F;code&gt; and &lt;code&gt;CONTRIBUTION.md&lt;&#x2F;code&gt; in a codebase.&lt;&#x2F;p&gt;
&lt;p&gt;Just stupid enough to code, and wise enough to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adventures.michaelfbryan.com&#x2F;posts&#x2F;rust-best-practices&#x2F;bad-habits&#x2F;&quot;&gt;avoid mistakes&lt;&#x2F;a&gt; (• ͡° ͜ʖ ͡°•)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-did-you-write-this-gone-nuts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-did-you-write-this-gone-nuts&quot; aria-label=&quot;Anchor link for: why-did-you-write-this-gone-nuts&quot;&gt;Why did you write this? Gone nuts..&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I am having imposter syndrome for good. God has blessed me, as I got the opportunity to work and learn from really senior engineers (like Staff engineers and CTOs were directly mentoring me, they were GOATed). I hope 2025 will treat me better :)&lt;&#x2F;p&gt;
&lt;p&gt;I went ahead and wrote about Rust a lot more than whether I should be a SWE or not. The thing is, I have improved a lot since 2024, but I still ask myself, am I good enough for anyone to hire me to build something cool? Am I that good yet? I guess I should just keep my head down and keep working hard. No point overthinking stuff.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t know why you are reading this, but thanks චᆽච&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The frenzy of building and observing seniors!</title>
          <pubDate>Tue, 26 Nov 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/building/</link>
          <guid>https://harsh-ps-2003.github.io/writes/building/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/building/">&lt;p&gt;I have started to experiment with a tons of pretty projects whenever I get some free time, I just love building some stuff. I recently tried making small local projects from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;codecrafters-io&#x2F;build-your-own-x&quot;&gt;build-your-own-x&lt;&#x2F;a&gt;. At first it doesn’t make much sense why somebody is trying to minimally re-implementing every other cool piece of technology he sees, but it just enlightening (feels cool basically) to me (although my frenzy lost its heat after some time, just wrote too much code, burned out).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-i-am-doing-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-i-am-doing-it&quot; aria-label=&quot;Anchor link for: why-i-am-doing-it&quot;&gt;Why I am doing it?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After having deep enough technical knowledge on how systems are working in it’s core, you will be able to troubleshoot effectively find solutions to the problems due to the breadth of code that you have exposed yourself to. Also it will make debugging the software more fun and less daunting as now you know how everything is working from the very roots. &lt;strong&gt;I guess I am god’s chosen IC :)&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Understanding the outsourced technologies used by your product is the key to optimizing them for your specific business needs as well as making right decisions between many options. I don’t mean to say that you should know everything deeply, but whatever you are working on in your day job, it just becomes a lot more beautiful and elegant when you take some time out (ideally your employer gives you some help (time and resources) when you want to improve as an employee) and get a solid birds-eye view on the technology empowering the business! At least that’s what I feel. I am a student, and this is no advice, just feelings, and I can feel whatever I want :-)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-instances-that-come-to-my-mind&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#some-instances-that-come-to-my-mind&quot; aria-label=&quot;Anchor link for: some-instances-that-come-to-my-mind&quot;&gt;Some instances that come to my mind&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A lot of bitter sweet memories come to my mind when I think about this ;) Some from my own work experience, some from just reading, some from being there when some staff guy takes interview for hiring other senior folks!&lt;&#x2F;p&gt;
&lt;p&gt;When I was involved with Jenkins in Google Summer of Code (I am maintaining stuff at Jenkins as well these days), I encountered a very peculiar problem related to Docker internals involving &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;blog&#x2F;2023&#x2F;02&#x2F;02&#x2F;docker-on-macos-is-slow-and-how-to-fix-it&#x2F;&quot;&gt;OSXFX because I was on Mac&lt;&#x2F;a&gt; and Linux System Integrity Protection which was daunting as hell. I discussed with the maintainers in the community and after long investigation, they were able to help me out. While working on the GSoC project I had to debug the jenkins plugins to the point that I was tinkering with the stapled object over HTTP exceptions (static resources sent with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;16691506&#x2F;what-is-gzip-compression&quot;&gt;gzip&lt;&#x2F;a&gt;), and old JSP thingy that I hope I will never encounter in my life again!&lt;&#x2F;p&gt;
&lt;p&gt;There were multiple instances when I had to step up to fix the libraries consumed by the plugin which were a real pain (those super busy maintainers just don’t respond quickly and the internship was for 3 months only, typical software engineering deadline prediction issues). These incidence helped me appreciate the importance of low level systems knowledge, I didn’t even knew what difference using different file systems in Docker could cause in performance and why (if you think, oh! its just a stupid file system, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.allegro.tech&#x2F;2024&#x2F;03&#x2F;kafka-performance-analysis.html&quot;&gt;this&lt;&#x2F;a&gt; is a perfect example on why you should care about your silly file system being used to optimize performance). Like, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jirevwe.github.io&#x2F;exploring-alternatives-to-uuidv4-enter-ulids.html&quot;&gt;UUIDs are commonly used, but alternatives exist as well!&lt;&#x2F;a&gt;. Thinking deeply before jumping is what I learnt! Like plan properly.&lt;&#x2F;p&gt;
&lt;p&gt;Now when I look back on the patches and fixes feel less scary as I worked quite a lot on my Software Engineering fundamentals. Weird though, they don’t teach these things in degree, CS degree seems to be pretty weird for me, seems like they are preparing you to do a Masters, then a PHD and then do research&#x2F;teaching, the degree is too theoretical for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ics.uci.edu&#x2F;~fielding&#x2F;pubs&#x2F;dissertation&#x2F;software_arch.htm&quot;&gt;Software Engineering&lt;&#x2F;a&gt; roles. People can take Software Engineering degrees as well, they are better bang for the buck I feel! But nevertheless, a CS degree is really good if you wanna go the research route. Fuck it, any STEM degree is cool, I love STEM.&lt;&#x2F;p&gt;
&lt;p&gt;Hilariously, I met a MIT Chemistry sophomore who wrote better Rust code than most CS fresh grads! Its quite a joke, CS seems to be the easiest STEM degree. Real chads study EE and Aerospace Engineering and ship rockets, not software. Most software is mental masturbation anyways. ◔̯◔&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interviewing-nuggets&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#interviewing-nuggets&quot; aria-label=&quot;Anchor link for: interviewing-nuggets&quot;&gt;Interviewing Nuggets&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Its fun listening to senior&#x2F;staff engineers on their interviewing experience. More fun when you get to see senior folks interviewing each other. I used to watch recordings of interviews during my intership when senior engineers were hired. Some interesting insights I got from there.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;i-need-to-make-sure-i-know-the-basics&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-need-to-make-sure-i-know-the-basics&quot; aria-label=&quot;Anchor link for: i-need-to-make-sure-i-know-the-basics&quot;&gt;I need to make sure I know the basics!&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;I realized that Staff+ folks generally go very deep into basic things that people generally overlook. Even when Staff guys solve Leetcode questions, they propose multiple approaches and solutions, &lt;strong&gt;they discuss tradeoffs, not solutions&lt;&#x2F;strong&gt;. Ofcourse that question can be solved by Dynamic programming, but we are strictly focused on optimizing time only, so use Greedy. As everybody seems to be a Leetcode monkey these days (I have seen people solving more than 500+ LC questions, which is absolutely insane), interviewers sometimes ask unoptimized solutions, focusing on improving a specific thing. But personally, I don’t know why senior folks are asked to Leetcode, work on weekdays and Leetcode on weekends for job security sounds pretty bad to me :(&lt;&#x2F;p&gt;
&lt;p&gt;Even when they are asking about HTTP and some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ics.uci.edu&#x2F;~fielding&#x2F;pubs&#x2F;dissertation&#x2F;rest_arch_style.htm&quot;&gt;REST&lt;&#x2F;a&gt; stuff, it can go deep (don’t underestimate basics)! Content on REST is actually confusing, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=pspy1H6A3FM&quot;&gt;this&lt;&#x2F;a&gt; talk beats the hammer on the nail nicely. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Caching&quot;&gt;HTTP Caching&lt;&#x2F;a&gt; and optimizations are often missed by candidates!&lt;&#x2F;p&gt;
&lt;p&gt;The CAP theorem is foundational to Distributed Systems, when discussing about it in an interview, PACELC coming into the picture is taken as positive point by interviewers. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1509.05393&quot;&gt;CAP theorem’s oversimplification has already been critiqued&lt;&#x2F;a&gt;. Also to note here is that consistency in CAP is different than consistency in ACID transactions. &lt;code&gt;C&lt;&#x2F;code&gt; in ACID relates to a state of a database in general and &lt;code&gt;C&lt;&#x2F;code&gt; in CAP (or distributed systems in general) is about a single data item in a database. Physics is the real bottleneck here :) I saw a lot of folks getting tripped here. Like, a Master’s student whose thesis is on Distributed Systems overlooks such stuff was surprising to me. Candidates are not giving wrong answers, but half-answers, and that’s frustrating. Just punching in, there is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.phillipcarter.dev&#x2F;posts&#x2F;observability-cap-theorm&quot;&gt;CAP theory like concept in Observability as well&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;You might think I am joking, but some people who say they do async programming, don’t even know whats async in async programming!? Please don’t be this person. &lt;em&gt;Async&#x2F;await is not about creating multiple threads.&lt;&#x2F;em&gt; If that’s async, what the hell is multi-threading? Instead, it’s about asynchronous programming, where tasks can be paused and resumed without blocking the entire thread. Instead of running tasks in parallel (like threads or processes do), async frameworks use non-blocking operations and an event loop to manage tasks efficiently on a single thread. Most async systems rely on a single-threaded event loop for managing tasks. The async functions are represented as coroutines (lightweight functions that can pause and resume execution). You can also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2009&#x2F;08&#x2F;29&#x2F;co-routines-as-an-alternative-to-state-machines&quot;&gt;relate it to State Machines&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Coroutine (goroutines is just coroutines on steroids which are managed by &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www1.cs.columbia.edu&#x2F;~aho&#x2F;cs6998&#x2F;reports&#x2F;12-12-11_DeshpandeSponslerWeiss_GO.pdf&quot;&gt;go runtime&lt;&#x2F;a&gt; and not the OS, many goroutines are multiplexed onto a smaller number of OS threads, thus they are lighter) is not multithreading, just one thread inside user space (thus no context switching, hence lightweight)! Its not competing (thread racing), instead coordinating. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@ugurkinik&#x2F;goroutines-are-not-threads-958c53d0d7f0&quot;&gt;Goroutine is not a thread!&lt;&#x2F;a&gt;. When you await an operation, the current task (tasks are broken into non-blocking units) gives up control (yields) to the event loop, allowing it to execute other tasks. Async is an abstraction, a non-blocking &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KXuZi9aeGTw&quot;&gt;cooperative concurrency&lt;&#x2F;a&gt;, not necessarily threads or processes. Its useful to handle multiple I&#x2F;O tasks concurrently without blocking the program. Multi-threading (threads and processes) is for CPU-bound tasks. CPU can run only one thread at a time. Multiple tasks are handled “as if” in parallel, but they are executed one at a time on a single thread. Async does not really have anything to do with threads. Also it helps disambiguate things to noticing that the async run time schedules “tasks” not “threads”. So as to distinguish what the async run time schedules from typical POSIX like threads. They are closely related but fundamentally separate. You can have async execution within a single thread, sometimes this is even more performant than using a thread pool. Async execution just means that the event loop can be passed off to other tasks. Learn about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=OirftZJO-rk&quot;&gt;worker threads&lt;&#x2F;a&gt;! &lt;strong&gt;Threads are for working in parallel, async is for waiting in parallel.&lt;&#x2F;strong&gt; I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;divan.dev&#x2F;posts&#x2F;go_concurrency_visualize&#x2F;&quot;&gt;these&lt;&#x2F;a&gt; of concurrency patter really really cool. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pkolaczk.github.io&#x2F;memory-consumption-of-async&#x2F;&quot;&gt;A very solid benchmark comparison between Go and Rust for concurrency&lt;&#x2F;a&gt; for understanding stuff practically! Go was meant to simplify concurrent programming, but when I was doing FOSS work for Kubernetes and other CNCF projects, I saw lots and lots of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;3297858.3304069&quot;&gt;real world concurrency bugs&lt;&#x2F;a&gt;, which mostly arise from programmers not understanding these primitives. The typical misunderstood ones are :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The cooperative non-deterministic goroutine scheduler&lt;&#x2F;li&gt;
&lt;li&gt;Context and Timers creating channels under the hood&lt;&#x2F;li&gt;
&lt;li&gt;Write mutexes having higher priority than Read&#x2F;Write Mutexes&lt;&#x2F;li&gt;
&lt;li&gt;Non deterministic and still blocking&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you are on a single-core machine, using more threads is bad as they wont be running in parallel (just context switching giving illusion of parallelism). Single thread with concurrency will be better. More threads dosent magically mean more speed. Single-threaded code is often faster for pure CPU-bound tasks. But in case of I&#x2F;O bound tasks like web scraping 100s of websites, the CPU will be idle due to network latency - in this case multiple threads are a viable option as it’s better to have many threads ready to take over while others are waiting for network responses - so context switching is no longer pure overhead. Async will be even better. OS threads use Preemptive scheduling - the kernel can interrupt a running thread at any time to switch to another thread, no need for thread to “agree” to be paused, which is good for CPU bound tasks where we dont trust the tasks to behave properly. Coroutines and Green threads are based on cooperative scheduling - ask must manually yield and scheduler cannot forcefully pause the task. No context switch happens unless the task explicitly says. Thus very good for I&#x2F;O bound tasks. But if you forget to await (e.g., a big CPU loop without await), you can block the entire event loop!&lt;&#x2F;p&gt;
&lt;p&gt;These are hard topics to understand + carry a lot of misunderstanding around them, thus become a major source of bugs. Dont get me wrong, goroutines are great, but the way they are designed, a lot of resource leaks happen if you dont use them properly. In my opinion, Rust is better. Yes you pay the price for safe coding, you become slower, but Rust is dependable. And I like dependable and maintainable software.
Standard maps are not thread-safe by default in both, in Go if multiple goroutines try to read and write—or write and write—to the same map concurrently without explicit synchronization, it triggers a data race. Unlike some languages where a race results in silent data corruption, Go’s runtime includes a built-in race detector for maps. If a concurrent write is detected alongside other reads&#x2F;writes, the Go runtime will actively crash your program with a fatal error (concurrent map writes). You must either wrap a standard map with explicit synchronization primitives like a sync.Mutex &#x2F; sync.RWMutex, use Go’s concurrent-specific sync.Map (optimized for specific read-heavy&#x2F;append-only patterns), or use channel-based actor patterns. Rust’s standard HashMap is also not thread-safe, but Rust prevents you from making this mistake at compile time rather than letting it crash at runtime, which is something I like. Rust enforces thread safety using the Send and Sync marker traits. A standard &lt;code&gt;HashMap&amp;lt;K, V&amp;gt;&lt;&#x2F;code&gt; does not implement Sync by default. This means the compiler will throw a hard error if you attempt to share a raw reference (&amp;amp;HashMap) across multiple threads simultaneously. So,&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Go lets you do it anyway and crashes at runtime if you mess up.&lt;&#x2F;li&gt;
&lt;li&gt;Rust catches it during compilation and refuses to build the code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I psychologically feel safe with Rust due to its ownership and borrowing :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is only, ever, one owner of data&lt;&#x2F;li&gt;
&lt;li&gt;Ownership can be transferred — a move&lt;&#x2F;li&gt;
&lt;li&gt;Owned values can be borrowed temporarily&lt;&#x2F;li&gt;
&lt;li&gt;Borrowing prevents moves from occurring&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;maciej.codes&#x2F;2022-06-09-local-async.html&quot;&gt;Rust async programming is inclined towards multi-threading by default&lt;&#x2F;a&gt; causing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;async&#x2F;&quot;&gt;complexity completely unrelated to the task of writing async code.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Just another &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;eld5cs&#x2F;go_is_well_designed_language_actually#c_ezn9ql&quot;&gt;rust vs go bashing, by the infamous Zig creator&lt;&#x2F;a&gt; for fun ಠ⌣ಠ&lt;&#x2F;p&gt;
&lt;p&gt;Event Loop design and how they make web servers efficient is also a fun question often asked in backend interviews! Why Ngnix or NodeJS server better than Apache web server? In each Ngnix worker process after being forked by the master process, has an event loop. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.dan.drown.org&#x2F;event-loop&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; has decent explanation and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8aGhZQkoFbQ&quot;&gt;this&lt;&#x2F;a&gt; paired with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=KKM_4-uQpow&quot;&gt;this&lt;&#x2F;a&gt; is gold. Event Loops are used in Redis as well, so its a good concept to know about, and it was the solution for the 1990s “c10k” problem! Most NodeJS apps are slow because devs dont understand how Promises work! There is nothing wrong with the runtime. Using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&#x2F;Reference&#x2F;Global_Objects&#x2F;Promise&#x2F;all&quot;&gt;right native Promise functions help&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A sidenote, every engineer is habituated to look at a lots of logs (though AI is better at it)! Yet most senior engineers (these days they are expected to be DBAs as well) who know DBs aren’t able to talk about write-ahead logs, commit logs and transaction logs which is crucial in DB design. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;blog&#x2F;engineering&#x2F;distributed-systems&#x2F;log-what-every-software-engineer-should-know-about-real-time-datas-unifying&quot;&gt;This&lt;&#x2F;a&gt; I think is one of the best writeups to learn about the abstraction called LOG!&lt;&#x2F;p&gt;
&lt;p&gt;A very simple statement like &lt;code&gt;optimized table&lt;&#x2F;code&gt; can create a mess in the interview if you don’t actually know how your table got optimized in MySQL. Suppose you delete lots of records from a table, and you notice that the space was not reclaimed by looking at the table status! So you use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dev.mysql.com&#x2F;doc&#x2F;refman&#x2F;8.4&#x2F;en&#x2F;optimize-table.html&quot;&gt;OPTIMIZE TABLE&lt;&#x2F;a&gt; command to get the space back. You should know that you only marked the records as deleted, and thus, the space is still left to be reused by other insertion. This is done to avoid unnecessary fragmentation and performance degradation. The &lt;code&gt;OPTIMIZE TABLE&lt;&#x2F;code&gt; command simply temporarily creates a new table and copies over the data excluding the free space, and then swap with the original table. Thus, it locks the entire table, so the command shouldn’t be used in production during operating hours. And you know, try to avoid &lt;code&gt;SELECT *&lt;&#x2F;code&gt; especially in columnar DBs, its bad for performance. ORMs are for smart noobs :)&lt;&#x2F;p&gt;
&lt;p&gt;Very foundational questions can trip you up in an interview. Suppose you work in a team who handled large scale payment gateway. In such case, the payment went through the gateway but failed on client’s side? What if double invoice gets generated? How will you sync stuff? You will have to roll back the committed transaction either in the client’s side or gateway or bank. How will you make sure that the transactions are committed successfully? Remember, the cute SAGA pattern? Suppose, the payment is debited, but not credited? Inconsistent reads are also an issue! Simple solution is using a read-write lock or shared lock (exclusively reading or writing), but it has resource contention. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;morningcoffee.io&#x2F;multiversion-concurrency-control.html&quot;&gt;MVCC&lt;&#x2F;a&gt; is standard here, in which reading do not block writing and writing do not block reading and thus provide high throughput out of your database. Locks must be granular, as they make the program synchronous. And yeah, these terminologies are confusing, dirty read, phantom read and what not!&lt;&#x2F;p&gt;
&lt;p&gt;Weird enough, a lot of candidates didn’t know that there is multi-level cache in the CPU, so &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=IroPQ150F6c&quot;&gt;we need to do more stuff with CPU than memory&lt;&#x2F;a&gt;! In multi-threaded environment, thread safety is ensured using Locks or Synchronized keyword (semaphores and mutexes under the hood). When working with Distributed Systems, Cache coherence is something you should know about when interviewing for senior roles! Having a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ccemOqDrc2I&quot;&gt;basic understanding of caching techniques&lt;&#x2F;a&gt; helps a lot! When we want to achieve strong consistency, the distributed lock itself is a performance overhead. Cache versioning (&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.jmfaleiro.com&#x2F;blog&#x2F;post&#x2F;mvcc-isolation&#x2F;&quot;&gt;MVCC&lt;&#x2F;a&gt;) does not guarantee 100 percentage consistency as well but its better for performance. How often do you want to update which can lead to conflict between two threads executing their transactions? - If its frequent, go Pessimistic locking which will lock the critical section the threads want to execute, as it assumes that there will exist conflicts. If rare, Optimistic locking is better due to less resource contention as no explicit resource locking is required. Getting high throughput is extremely hard! Optimistic locking allows more throughput compared to Pessimistic locking, and is just better for performance. And &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=jIA7z1gxuc8&quot;&gt;Caching is HARD!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And ports are not in hardware, they are managed by kernel and are in L4 of OSI! I saw this mistake when interns were being interviewed. Sounds silly until they ask you very damn basic things in interview.&lt;&#x2F;p&gt;
&lt;p&gt;You know what, lets stoop soo low, whats the difference between IO vs CPU intensive? I&#x2F;O-bound tasks spend most of their time waiting for external operations to complete—like reading from disk, database queries, HTTP requests, etc. The CPU is mostly idle during this waiting period. Whereas, CPU-bound tasks require continuous CPU processing, such as data compression, cryptographic operations, large computations, etc. They don’t wait on external resources but keep the CPU busy. And what will you do when you want to handle both of them together? You shouldn’t perform CPU intense work on tokio blocking threads i.e. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;buraksekili.github.io&#x2F;articles&#x2F;thread-pooling-rs&#x2F;&quot;&gt;worker_threads() in thread pool&lt;&#x2F;a&gt;. Tokio assumes work on those threads will be I&#x2F;O bound, and so will spawn a lot of them on the assumption that individually they mostly spend their time blocking (you shouldn’t run CPU-bound tasks here because they’ll block the event loop, starving other async tasks). Place all the potentially blocking tasks into separate threads (with tokio’s &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt; for blocking I&#x2F;O tasks controlled via &lt;code&gt;max_blocking_threads()&lt;&#x2F;code&gt;) and use the async threadpool for the rest. Do not use &lt;code&gt;spawn_blocking&lt;&#x2F;code&gt; for your CPU heavy tasks. Rayon is optimized for parallel CPU-bound computations. Just offload CPU-heavy tasks to Rayon (or some custom thread pool), keeping both Tokio’s worker threads and blocking threads free.&lt;&#x2F;p&gt;
&lt;p&gt;Another simple thing, if you are asked, what’s the best way to store key value pairs in memory? And hashmap is your only answer and you stop after that, you are up for a wild ride my friend! First questions should be, whats the best for you? Hashmaps are not thread-safe by default and has unordered storage with hashing overhead. Yeah its O(1) I know, but what if that’s not our priority? BTreeMap is when you want ordered keys to deal with range queries and is okay with O(logn) inserts&#x2F;lookups. Hashmap can blow up based on their implementation but an ordered map (BTreeMap) implementation which uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;planetscale.com&#x2F;blog&#x2F;btrees-and-database-indexes&quot;&gt;BTree&lt;&#x2F;a&gt; (even Red-Black Trees are used for this, called TreeMap, for for large in-memory datasets, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1589556&#x2F;when-to-choose-rb-tree-b-tree-or-avl-tree&quot;&gt;BTree are more performant&lt;&#x2F;a&gt; and cache-friendly) won’t but it has logarithmic complexity in worst case which can be better in cases there are too many collisions or reshashing taking place, which will lead to O(n) worst (a recent &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2501.02305&quot;&gt;research paper&lt;&#x2F;a&gt; has improved it to (logn)^2 and it was done by a undergrad) , whereas BTreeMap will always have O(logn). So if worst case performance matters, don’t choose HashMap. And be prepared to explain stuff like rehashing, load factor and hash functions. If you say HashMap And, use DashMap instead of &lt;code&gt;Arc&amp;lt;RwLock&amp;lt;HashMap&amp;lt;K, V&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;code&gt; for concurrent access. Unlike Rust’s standard &lt;code&gt;HashMap&amp;lt;K, V&amp;gt;&lt;&#x2F;code&gt;, which requires wrapping in a &lt;code&gt;Arc&amp;lt;RwLock&amp;lt;HashMap&amp;lt;K, V&amp;gt;&amp;gt;&lt;&#x2F;code&gt; (causing contention on the entire map), DashMap internally splits data into multiple independent shards, each shard is a smaller, independently locked &lt;code&gt;HashMap&amp;lt;K, V&amp;gt;&lt;&#x2F;code&gt;. Instead of one global lock, DashMap only locks the critical shard on write operations, thus allowing multiple threads to modify different shards simultaneously, increasing performance. This sharded design significantly reduces contention (only a single shared is locked when writing) compared to a global &lt;code&gt;Mutex&amp;lt;HashMap&amp;lt;K, V&amp;gt;&amp;gt;&lt;&#x2F;code&gt;. The reads are lock free, multiple threads can read different keys in parallel without locking.&lt;&#x2F;p&gt;
&lt;p&gt;Metaprogramming is a very important paradigm used in modern languages like Rust and Nim (more powerful and flexible than Rust’s macros in some ways because they operate on full AST manipulation at compile time compared to token based AST manipulation in Rust) . The ability to have compile time code execution (unlike functions, which operate at runtime) is powerful to say the least, while DRYing up the code. Its the ultimate Boilterplate killer. Like we can have literal HTML with syntax highlighting in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=RfhkCdu3iYs&quot;&gt;Rust via procedural macros&lt;&#x2F;a&gt;, i.e DSL made fun. And yet, for some weird reason, so many programmers either don’t know about it, or don’t use it in its full glory! Why? The only caveat I can think of is that it makes debugging a bit harder. Like, if you want to implement similar methods for different structs, use macros. To avoid expensive runtime time computation, use macros. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;slinkydeveloper.com&#x2F;rust-macros-are-not-just-about-dry&#x2F;&quot;&gt;But Rust macros aren’t just for DRYing!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Last one, in a Request-Response architecture (chain dependent, can’t move ahead without response, unlike Event-driven, where a producer fires an event, and consumers react to it asynchronously without expecting a response) when using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grpc.io&#x2F;blog&#x2F;grpc-on-http2&#x2F;&quot;&gt;gRPC calls&lt;&#x2F;a&gt;, how is req-res paired? We don’t use any nonce to pair them up manually? It happens via &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;76730948&#x2F;will-2-unidirectional-identical-grpc-calls-open-2-http-2-connections-or-will-the&quot;&gt;HTTP&#x2F;2 multiplexing&lt;&#x2F;a&gt; which uses unique stream IDs.&lt;&#x2F;p&gt;
&lt;p&gt;Forward Proxy is used to protect the clients accessing the websites via the internet. It helps with Content filtering for the client, caching frequently requested resources, hiding client IP address, client request modification. Reverse Proxy is used to guard the web servers from the clients trying to access websites via the internet. It helps with server protecting from DDoS attack, hiding original IP address, load balancing, SSL management, content management. Mentioning this stupid thing as I myself tripped in an interview when asked about Reverse proxy setup in Jenkins. I didn’t knew why I setup reverse proxy for Jenkins plugins at the first place, it was part of project so I did it without asking my mentor what purpose it served :(&lt;&#x2F;p&gt;
&lt;p&gt;Oh, btw check out Nim. It’s for when you want to write low-level systems code but you don’t hate yourself and aren’t a masochist. Its a very powerful language, and can produce extremely small binaries. Zig could be the modern C, and Rust the modern C++. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brianlovin.com&#x2F;hn&#x2F;31160234&quot;&gt;Nim doesn’t seem to have a purpose, its feel like a weirdly good general for everything sort of a language, which has a marketing problem as nobody uses it for some reason!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dzone.com&#x2F;articles&#x2F;logical-reasoning-in-network-problems&quot;&gt;A very cool blog to understand logical reasoning when troubleshooting network issues!&lt;&#x2F;a&gt;. I am bad at this!&lt;&#x2F;p&gt;
&lt;p&gt;If I see MongoDB in someone resume then I would expect them to atleast know about writing complex queries and aggregation, have an understanding of how indexing work internally in MongoDB and efficient way to design schema, ESR rule, sharding in MongoDB and how to implement it.&lt;&#x2F;p&gt;
&lt;p&gt;I need to practice writing consensus algorithm, god knows when some interviewer asks me to do so in a 40 min interview (ー_ー；)&lt;&#x2F;p&gt;
&lt;p&gt;Or worse, one senior guy I know told me that he was interviewing for some HFT Rust role, and they literally asked him to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.rochester.edu&#x2F;~scott&#x2F;papers&#x2F;1996_PODC_queues.pdf&quot;&gt;implement a lock-free queue&lt;&#x2F;a&gt; from scratch in a 40min interview!!!!!&lt;&#x2F;p&gt;
&lt;p&gt;And it’s so embarrassing when someone asks you the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.phoenix.edu&#x2F;blog&#x2F;scripting-vs-programming-languages.html#3&quot;&gt;difference between scripting language and programming language&lt;&#x2F;a&gt;, and you fumble badly ( &amp;gt;︹&amp;lt;)&lt;&#x2F;p&gt;
&lt;p&gt;And yeah, if somebody is thinking, why you need to know about these CS stuff, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;milomg.dev&#x2F;2022-12-01&#x2F;reactivity&quot;&gt;I am just going to be a frontend engineer, knowledge of algorithms are still crucial!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After reading all these interview nuggest, you must be having a PTSD (@д@) but whatever I wrote, I have watched first-hand in interview recordings. So maybe we are destined to be a goose-farmer if you are dumb like me ◔_◔&lt;&#x2F;p&gt;
&lt;h3 id=&quot;btw-even-i-fucked-up-in-an-interview-once&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#btw-even-i-fucked-up-in-an-interview-once&quot; aria-label=&quot;Anchor link for: btw-even-i-fucked-up-in-an-interview-once&quot;&gt;Btw, even I fucked up in an interview once&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I am no god, so let me explain you a question which I messed up during a very casual interview. I was being interviewed by a Principle Engineer, and I thought, because the guy is very senior he will ask me some mind-numbing question. I couldn’t be more wrong. I was asked a very very simple question, but he made me shit my pants with his followup!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set(key, value): Sets a specific key to a given value.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;setAll(value): Sets all keys to the same value.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;get(key): Returns the value of a specific key.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The challenge was to optimize it so that `set_all` doesn’t take too long when you call get or set after it.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The naive &lt;code&gt;set_all&lt;&#x2F;code&gt; implementation is O(N). Ofcourse he wants me to do better so I optimized the &lt;code&gt;set_all&lt;&#x2F;code&gt; like this :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;collections&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;HashMap&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizedMap&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; key -&amp;gt; (value, set_version)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    global_value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    global_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; can be thought as a timestamp as well&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizedMap&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            global_value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            global_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; set_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_version &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_value &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_version &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_value&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizedMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; version - 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 20&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;set_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; version - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 30&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; version - 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ Some(100) (from global_value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ Some(100) (from global_value)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ Some(30)  (explicitly set after set_all)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ✅ None      (never existed)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all three are O(1)! I was happy :)
But he was even happier ⊂◉‿◉つ and asked me for a rollback implementation. So I did this :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;collections&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;HashMap&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizedMap&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; key -&amp;gt; (value, set_version)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    global_history&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (global_value, global_version)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    current_global_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizedMap&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        Self&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            global_history&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Initial version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            current_global_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_global_version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; set_all&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_global_version &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_history&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_global_version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_global_version &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Find the global value at the time the key was last updated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;rev&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; val&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; rollback&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; target_version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Check if the target version exists in history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;global_value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;global_history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;find&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; v&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; target_version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_global_version &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; target_version&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;            true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;            false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, I straight up thought about rollback, not whether it will be frequent or not. Don’t be like me, ask good questions to the interviewer. Rollback is O(N) here! Ofcourse he wanted better, and unfortunately I started thinking of some fancy algorithm to make the rollback faster. And when I couldn’t come up with some way, I was dead in the interview (-_-; ). Don’t be silent in any fucking interview. Speak something! The solution was simple, just use &lt;code&gt;BTreeMap&lt;&#x2F;code&gt; in case of frequent rollbacks to specific versions. If rollbacks are rare, &lt;code&gt;Vec&lt;&#x2F;code&gt; is just fine! But this thought just didn’t come in my mind during the interview. I passed somehow!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-hard-to-find-cracked-folks-not-bluffers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-hard-to-find-cracked-folks-not-bluffers&quot; aria-label=&quot;Anchor link for: it-hard-to-find-cracked-folks-not-bluffers&quot;&gt;It hard to find cracked folks, not bluffers&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is a thing I saw when binging a lot of recordings.
Stop bluffing and exaggerating. When working with engineers, its quite easy to call the bullshit! I have enjoyed working with people (in OSS and when mentoring some folks) who are cut-throat truthful about what they don’t know about! Like really, some junior engineers don’t know much (which is okay! they should not! even though I feel the tech industry borderline hates junior engineers atp) but atleast be honest, and build yourself up truthfully, and don’t brag to the moon instead work hard. Using EGO productively is under-rated! One weird thing these days in that, senior engineers are expected to have working knowledge of the whole IT department of the company :-( which is undue pressure on one individual! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=66KAwhhwOEk&quot;&gt;Avoid solving imaginary scaling problems!&lt;&#x2F;a&gt;, most problems in programming are already solved, don’t make unnecessary fuss!&lt;&#x2F;p&gt;
&lt;p&gt;Often, you learn about the details of what you are using when you have a deep dive out of curiosity (re-implementing some stuff in any other language is often fruitful to learn deeply about that language as well). So, when having less workload, its wonderful to let your curiosity take you into wild directions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nmn.gl&#x2F;blog&#x2F;ai-and-learning&quot;&gt;If you write a piece of code using AI, and you dont know how it works, my pal, you are doomed!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;should-i-be-an-ic-or-a-manager-when-i-grow-up&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#should-i-be-an-ic-or-a-manager-when-i-grow-up&quot; aria-label=&quot;Anchor link for: should-i-be-an-ic-or-a-manager-when-i-grow-up&quot;&gt;Should I be an IC or a manager when I grow up?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Don’t forget to share what you learn though! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=q-7l8cnpI4k&quot;&gt;Social skills are necessary for Geeks as well!&lt;&#x2F;a&gt;. People should know why are you suddenly refactoring all that somehow working code and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=y376JcBl1t8&quot;&gt;deleting thousands of lines&lt;&#x2F;a&gt; :)&lt;&#x2F;p&gt;
&lt;p&gt;But in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=OTCuYzAw31Y&quot;&gt;technical leadership and working with people&lt;&#x2F;a&gt; (I haven’t really had a decent long chat with techno-managerial folks till now), the coding will take a back seat if you are not curious enough about whats actually happening in your team! There is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0SARbwvhupQ&quot;&gt;no Genius Programmer&lt;&#x2F;a&gt; but there sure are egoist programmers! But nevertheless, there are joys of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=skD1fjxSRog&quot;&gt;engineering leadership&lt;&#x2F;a&gt; as well as writing some clean code &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=4F72VULWFvc&quot;&gt;this&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=-FRm3VPhseI&quot;&gt;that&lt;&#x2F;a&gt; if you continue to be an IC. Coolest thing I can imagine doing as a manager is looking at the code from a business point of view, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=czes-oa0yik&quot;&gt;metrics would be so important for me&lt;&#x2F;a&gt;! The idea of &lt;strong&gt;Centralized vision and its Decentralized execution&lt;&#x2F;strong&gt; is very cool to me! But managers have a lot of meetings, and I don’t like meetings!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;where-is-my-girl-gang&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-is-my-girl-gang&quot; aria-label=&quot;Anchor link for: where-is-my-girl-gang&quot;&gt;Where is my Girl gang …&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;One sad thing that I noticed is, there are less women engineers in cutting-edge startups for some reason. I have interacted with ample of girls who went to big tech, but none who went to startups. Sad life :(
Why are startups so male-dominated, weird? I guess big tech push on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.cleancoder.com&#x2F;uncle-bob&#x2F;2017&#x2F;10&#x2F;04&#x2F;WomenInDemand.html&quot;&gt;diversity hiring&lt;&#x2F;a&gt; is what’s driving it maybe. Man I love girlies 💅&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-guess-i-have-too-much-free-time&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-guess-i-have-too-much-free-time&quot; aria-label=&quot;Anchor link for: i-guess-i-have-too-much-free-time&quot;&gt;I guess I have too much free time&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;I have just ranted my thoughts here! I have an exam after some time, and I guess I am up for some bad grades :)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;These are just my personal experiences, observations and learning from others mistakes, not some wisdom, just some things that came to my mind at some random days&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Another reason writing this up is revision of crucial CS concepts when interviews come up!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Working at a early-stage startup!</title>
          <pubDate>Fri, 25 Oct 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/working-at-a-early-stage-startup/</link>
          <guid>https://harsh-ps-2003.github.io/writes/working-at-a-early-stage-startup/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/working-at-a-early-stage-startup/">&lt;p&gt;So, I got hired at a startup at the end of my 2nd year at IITK, and man it was an intense experience working at a high growth startup! I was working, managing my academic workload and later started doing some cryptography research project under a cool prof as well, so hectic as fuck. But I loved every single moment of it. I learned about the experience of working in a startup, and some nuggets on what it takes to actually run a high-growth startup.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-was-it-different&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-was-it-different&quot; aria-label=&quot;Anchor link for: how-was-it-different&quot;&gt;How was it different?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I had some internships under by belt which were also pretty solid experience technically, but not organizationally. In internship, I used to get a mentor assigned to me, I had to simply propose a timeline of how I plan to finish up the internship work and the mentor would guide me while I do the work, great if you want to improve technically. But the startup experience is totally different. I was not an intern anymore (umm… I actually was, but my CTO just trusted me to assign a project to me completely). People were actually dependent on my work. I found out that I am not that good at timeline estimation. And a lot of things don’t go the way you thought initially, especially when you work in a team.&lt;&#x2F;p&gt;
&lt;p&gt;When issues happen upstream (you are dependent on someone), shit hits the fan! People don’t reply fast, maintainers of OSS are really busy people, talking to Product Managers to reach out to devs responsible for the issue to the tech lead, getting the issue resolved, giving feedback to the managers, and then returning back to your own work. Unblocking other team memebers time to time. The hardest part is not technical, but communication and management.&lt;&#x2F;p&gt;
&lt;p&gt;Nobody is there to clean up your mess - technical debts, people who left the role, sudden breaking change in god knows what lib that you were using, … Reducing your &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;deviq.com&#x2F;terms&#x2F;bus-factor&quot;&gt;bus factor&lt;&#x2F;a&gt; is very crucial.&lt;&#x2F;p&gt;
&lt;p&gt;I was not working on a personal project! I can’t add any new dependencies, use a new language like Rust :) and implement new libraries that wrap something, and show that to the team expecting appreciation. Bad idea, always discuss first with the team, and then do stuff. Don’t try to be smart, and end up being a smart-ass.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;inelpandzic.com&#x2F;articles&#x2F;i-love-tecnical-debt&#x2F;&quot;&gt;Technical debt is not bad, but neglected technical debt is!&lt;&#x2F;a&gt; &lt;code&gt;Talk is cheap! Show us the code&lt;&#x2F;code&gt; is a really bad idea! Maintaining the codebase is a large part of the job.&lt;&#x2F;p&gt;
&lt;p&gt;Also, the amount of time you will spend in meetings in just mindnumbing. But attending meetings is not a waste of time at all. Sharing the right information and mentoring juniors is absolutely essential. A culture of sharing information avoids the situation of a star dev in the team. And supporting your manager is crucial to manage you is crucial.&lt;&#x2F;p&gt;
&lt;p&gt;Senior engineers are often judged by the performance of the team they are leading, apart from their own performance. You will have to actively stay in loop on where the team is stuck.&lt;&#x2F;p&gt;
&lt;p&gt;As a student I used to think it’s hard to get hired. Well, it’s way harder to find someone competent and accountable enough to show up everyday with grit and determination.&lt;&#x2F;p&gt;
&lt;p&gt;But I guess, I just love the thrill of working in a startup, creating products that shoot to production fast! I am still waiting for the day when I delete my first production server as a cute intern :) The feedback loop and learning speed at a high-growth startup is just hypnotic (work life balance goes for a toss). Well, you will have bad WLB even in big tech these days, so not much of a loss. But I still wanna try Big Tech and Quants just out of FOMO once.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wait-before-you-sign-that-offer-big-boy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wait-before-you-sign-that-offer-big-boy&quot; aria-label=&quot;Anchor link for: wait-before-you-sign-that-offer-big-boy&quot;&gt;Wait before you sign that offer big boy&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The easiest kind of offer you can aim for is an intern-to-full-time conversion offer. The intern interview process can be atleast twice easier than a full-time interview process. But observe the company very keenly before accepting that offer. A solid internship gives you levrage to get even better full-time roles if you are ready to take a risk and work hard. You don’t always have to accept the conversion offer.&lt;&#x2F;p&gt;
&lt;p&gt;Although I am just a student and have no corporate 10+ years of leadership experience, still some points that I have started to consider before accepting offer to join any company :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Performing good in interviews don’t have much to do with performing good in job. Those behavioural rounds are useless, repetitive crap. I have seen many companies try to sell you on their culture or ‘core values.’ But honestly, you can forget about most of that after the interview Can people in your team get shit done? Find out who gets most shit done, and learn from them as an intern especially. These technical interviews are necessary-evil.&lt;&#x2F;li&gt;
&lt;li&gt;Being fast in software is not the best idea. If your task is estimated to take two days and you finish in two hours, no one really cares or remembers your name. but, if a bug comes from that code, everyone will remember you. So being fast isn’t always valuable.&lt;&#x2F;li&gt;
&lt;li&gt;Avoid teams who have heroic coders, they just don’t have process setup properly. And that cute hero is borderline mentally harassed. Also, beware of information hoarders (happening quite a lot in big tech due to layoffs), there are manipulative people everywhere, stay sharp.&lt;&#x2F;li&gt;
&lt;li&gt;Work with smart folks, not smart-asses. You really underestimate humility before you meet egoists. I don’t join a team where everybody is a genius. I like working with normal human beings, not with 100x engineers. Work with folks who humbly handle the tech-debt and do boring but necessary stuff in the company, not drive impact to the moon while throwing other engineers under the bus. These smart-asses rock the interview, but are a nightmare to work with. I’d rather work with someone who isn’t a genius but is willing to collaborate and share ideas. Stay away from over-competing folks, spend more time with your girlfriend or wife, pursue hobbies, life you precious life please.&lt;&#x2F;li&gt;
&lt;li&gt;High turnover rate is redflag, and the company clearly isn’t able to appreciate the talent.&lt;&#x2F;li&gt;
&lt;li&gt;If you are interviewing for an intern position, during the interviews, ask about the kind of tasks you’ll do in the role, the manager you’ll report to, and the kind of mentorship you’ll get. If you are an intern, you shouldn’t be simply thrown into the project (ideally, but a lot of times if its a startup, be ready for some serious action). Fight for the team and mentorship, they are gonna define your internship as well as full-time conversion.&lt;&#x2F;li&gt;
&lt;li&gt;Don’t shy away from negotiation even for internship. Even if you don’t work for money, you have every right to be paid your worth.&lt;&#x2F;li&gt;
&lt;li&gt;Always have other offers. I’ve seen two friends with similar experience joining the same company for the same role, but one got $50k more a year because he had a competitive offer.&lt;&#x2F;li&gt;
&lt;li&gt;Focus only on the take-home money. No stocks, bonuses, hikes, yada yada. They can be gamed against you.&lt;&#x2F;li&gt;
&lt;li&gt;Read Glassdoor&#x2F;Blind reviews to get a sense of what you’re getting into. Heck, DM employees on LinkedIn to get a feel of how the company is from inside.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;If the only thing that your job is paying you is money, better find another job.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, I wish to work on something worthwhile, not just print money. This comes with a sense of entitlement that money is not hard for me to make. Great engineers are sought after a lot…&lt;&#x2F;p&gt;
&lt;p&gt;Also, discuss everything over emails, not on telegram, discord, slack, etc. And negotiate, always! Over-confidence is better than under-confidence (not humility) most of the times.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-dropped-the-thought-of-building-company-being-in-college&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-dropped-the-thought-of-building-company-being-in-college&quot; aria-label=&quot;Anchor link for: i-dropped-the-thought-of-building-company-being-in-college&quot;&gt;I dropped the thought of building company being in college&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Don’t trying building a company when in university! Either drop-out or take a year gap to iterate. Otherwise you will have a lot on your plate. Always work in a startup before starting one. Organizing an engineering team is really hard, and you will have to give them an optimal employee experience as well. They are an employee, you are a founder. So you cant expect them to work like a founder. Building accountability systems should be a priority. Raising VC money is extremely hard as a student. An accelerator program is not real progress (even if its YC). Do you really wanna do this, are you obsessed enough?&lt;&#x2F;p&gt;
&lt;p&gt;I was not. Period. Maybe some other day, some other time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-learnt-about-myself&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-learnt-about-myself&quot; aria-label=&quot;Anchor link for: what-i-learnt-about-myself&quot;&gt;What I learnt about myself&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Atleast for the time being, research will be on my cards. I really underestimated managing people. &lt;em&gt;I am the god’s chosen IC&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Wealth</title>
          <pubDate>Wed, 04 Sep 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/reads/finance/</link>
          <guid>https://harsh-ps-2003.github.io/reads/finance/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/reads/finance/">&lt;p&gt;Its hard to earn money, and harder to keep it with you.&lt;&#x2F;p&gt;
&lt;p&gt;Books :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Little Book of Common Sense Investing&lt;&#x2F;li&gt;
&lt;li&gt;Common Stocks &amp;amp; Uncommon Profits&lt;&#x2F;li&gt;
&lt;li&gt;Big Debt Crisis&lt;&#x2F;li&gt;
&lt;li&gt;The Mastery of Capital&lt;&#x2F;li&gt;
&lt;li&gt;Lets talk Money&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Starting to pick up Nix a bit!</title>
          <pubDate>Wed, 31 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/nix/</link>
          <guid>https://harsh-ps-2003.github.io/writes/nix/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/nix/">&lt;p&gt;Well, most modern programming languages come with package managers that help manage dependencies, and among other things they do their best to ensure that they aren’t altered without the user knowing. There are always more sources of variability than you can count. If you are dealing with systems software, the surface area increases even more as now you have to worry about native libs, compilers, OS, might be kernel as well! More often that not, figuring out what the previous state of the system was is a herculean task. Only if you are unlucky that the burden of hunting for differences can land upon you like a divine punishment.&lt;&#x2F;p&gt;
&lt;p&gt;One of the core ideas behind modern dependency managers lockfiles, view of the dependencies that were locked in at some point. Among other data, this includes the package location, its precise version, and a checksum to ensure it’s not tampered with or corrupt. I wanted similar level of control on a larger scale. Thats when I stumbled upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Nix_(package_manager)&quot;&gt;Nix&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;into-the-rabbithole&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#into-the-rabbithole&quot; aria-label=&quot;Anchor link for: into-the-rabbithole&quot;&gt;Into the rabbithole&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While investigating &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.replit.com&#x2F;tutorials&#x2F;python&#x2F;build-with-nix#how-can-we-use-nix-on-replit&quot;&gt;how repl.it used Nix to secure the access to their running containers&lt;&#x2F;a&gt;, I went down the Nix rabbit hole for a week and became a bit more &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;NixOS&#x2F;comments&#x2F;kauf1m&#x2F;dealing_with_post_nixflake_god_complex&#x2F;&quot;&gt;enlightened&lt;&#x2F;a&gt;. Also, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nixpacks.com&#x2F;docs&quot;&gt;Nixpacks&lt;&#x2F;a&gt; piqued my interest due to its capability of being able to generate OCI complaint container images from any Nix supported dependencies directly (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.qovery.com&#x2F;blog&#x2F;my-feedback-about-nixpacks-an-alternative-to-buildpacks&#x2F;#cons&quot;&gt;though its not perfect&lt;&#x2F;a&gt; and I should contribute to it maybe). Folks using Fly.io to deploy literally having &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;community.fly.io&#x2F;t&#x2F;running-reproducible-rust-a-fly-and-nix-love-story&#x2F;3781&quot;&gt;love stories&lt;&#x2F;a&gt; with Nix :) Interestingly I also remembered that Saksham (one of my awesome seniors at IITK) also wrote about it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sakshamsharma.com&#x2F;2018&#x2F;03&#x2F;docker-hakyll-builds&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; which made me double down on Nix. The positive impact of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;determinate.systems&#x2F;posts&#x2F;nix-home-env&#x2F;&quot;&gt;Nix driven workflow&lt;&#x2F;a&gt; is clearly visible by the amount Nix community has grown! This writeup is what I hoped I had before challenging myself with this steep Nix learning curve. This is not to learn about using Nix in your workflows (though I have linked some great blogs from some super smart folks), but to serve as a collection of useful resources for anyone starting out, a headstarter!&lt;&#x2F;p&gt;
&lt;p&gt;Here I am focused on Nix as a package manager (nixpkgs as a central repository of nix packages), an immutable graph database &lt;code&gt;nix-store -q --tree result&lt;&#x2F;code&gt; (cool diagrams &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;skip.house&#x2F;blog&#x2F;nix-in-practice&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;) and a build system thingy. When nix builds something, it’s stored in &#x2F;nix&#x2F;store, which is essentially an immutable graph database, with a hash that encodes this full dependency graph. In developer workflows, we can use &lt;code&gt;mkShell&lt;&#x2F;code&gt; for using &lt;code&gt;nix develop&lt;&#x2F;code&gt;. For a more wholesome explanation refer this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2022-07-14-taming-unix-with-nix&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The concept is simple, we just read a Nix expression and derive the build with specific build inputs. We can also fetch from the cache, the needed inputs and final derivation.&lt;&#x2F;p&gt;
&lt;p&gt;The advantage of Nix is in getting your developement, CI and production in sync (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jetpack.io&#x2F;blog&#x2F;devbox-build-your-docker-image-from-scratch&#x2F;&quot;&gt;Devbox in their internal dev workflow&lt;&#x2F;a&gt; suffered through this), also having the power of cross compilation, i.e consistent environment accross development, making it the single source of truth. Yeah! Things would just work… You get always-working environments with little to no duplicated effort. Basically avoid a green check mark on a PR only to realize that the production is broken. Whereas Docker (with K8s) is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.aquasec.com&#x2F;a-brief-history-of-containers-from-1970s-chroot-to-docker-2016&quot;&gt;container-based deployment solution&lt;&#x2F;a&gt; which have become so popular, that they have set a high standard when it comes to organizing systems and automating deployment. today, in many environments, I have the feeling that it is no longer the question what kind of deployment solution is best for a particular system and organization, but rather, “how do we get it into containers and deploy it into microservices?”. Docker is partially fit for this (unless you aggressively play with versions) and this concept of Reproducible vs Repeatable builds is very well explained in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0uixRE8xlbY&amp;amp;t=47s&amp;amp;pp=ygUcZmxha2VzIGluc3RlYWQgb2YgZG9ja2VyZmlsZQ%3D%3D&quot;&gt;this&lt;&#x2F;a&gt; talk.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;docker-and-nix&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#docker-and-nix&quot; aria-label=&quot;Anchor link for: docker-and-nix&quot;&gt;Docker and Nix&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Docker approached building Container Images (immutable self-contained root file systems containing all necessary files to run a program, such as binaries, libraries, configuration files etc) in multi-stage builds. As a best practice, ‘scratch’ image (
though I am casually calling it base image, its not, its totally empty, yes! not even shell is there. The way container images are constructed is that it makes use of the underlying Kernel providing only the tools and system calls that are present inside the kernel. Because in Linux everything is a file you can add any self-contained binary or an entire operating system as a file in this filesystem. This means that when creating an image from Scratch, technically refers to the Kernel of the host system and all the files on top of it are loaded. That’s why building from Scratch is no also a no-op operation and when adding just a single binary the size of the image is only the size of that binary plus a bit of overhead. The resources assigned when executing an image in a container is by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=sK5i-N34im8&quot;&gt;leveraging the cgroups and the networking makes use of the linux network namespacing&lt;&#x2F;a&gt; technique
), starkly different from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GoogleContainerTools&#x2F;distroless&quot;&gt;Distroless Image&lt;&#x2F;a&gt; which I often see used other than parent images when the code cannot be complied directly to a single runnable binary. Thus the container life-cycle is bound to the life-cycle of a root process, that runs in an isolated environment using the content of a Docker image as its root file system.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, to optimize&#x2F;reduce storage overhead, Docker uses layers and a union filesystem (there are a variety of file system options for this) to combine these layers by “stacking” them on top of each other.&lt;&#x2F;p&gt;
&lt;p&gt;A running container basically mounts an image’s read-only layers on top of each other, and keeps the final layer writable so that processes in the container can create and modify files on the system.&lt;&#x2F;p&gt;
&lt;p&gt;Whenever you construct an image from a Dockerfile, each modification operation generates a new layer. Each layer is immutable (it will never change after it has been created) and is uniquely identifiable with a hash code, similar to Nix store paths.&lt;&#x2F;p&gt;
&lt;p&gt;But if you can create Container Images with Nix &lt;code&gt;dockerTools&lt;&#x2F;code&gt;, boasted by Nix on their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;#asciinema-demo-example_4&quot;&gt;homepage&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nix.dev&#x2F;tutorials&#x2F;nixos&#x2F;building-and-running-docker-images.html&quot;&gt;doc&lt;&#x2F;a&gt; as well as Dockerfiles, then why mess your brain up with Nix and simply not use Dockerfile? Nix v&#x2F;s Docker to generate OCI complaint docker images is surely a heated question catered well by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.replit.com&#x2F;nix-vs-docker&quot;&gt;this&lt;&#x2F;a&gt;. Its universally known that smaller images with less bloat lead to a smaller attack surface and probably increased security and faster deployments. So lets compare the three options we have to get our PERFECT container image looking for build speed from caching, maintainability, security:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Using traditional Multistage builds
Many DockerCon talks like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=JofsaZ3H1qM&amp;amp;t=60s&quot;&gt;this&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=zF9bkkjIQWM&quot;&gt;this&lt;&#x2F;a&gt; covered the best practices while writing Dockerfiles, and as you can see, writing good Dockerfiles becomes increasingly difficult as you try to incorporate best practices. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jpetazzo.github.io&#x2F;2020&#x2F;03&#x2F;01&#x2F;quest-minimal-docker-images-part-2&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; blog highlights the size comparison using various dockerfile techniques. You’ll see that the base image contains many files we might not need or want, things that potentially could be a security problem. It comes bundled with tools such as sh, wget, and the apk. The nix image will have no such tools - only nginx and its dependencies.&lt;&#x2F;li&gt;
&lt;li&gt;Using Nix dockerTools
Although this method to create container image has been there for years, recent &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grahamc.com&#x2F;blog&#x2F;nix-and-layered-docker-images&#x2F;&quot;&gt;caching optimization&lt;&#x2F;a&gt; has made it a very appealing choice.
The functional approach rewards with better abstraction. The Hydra CI server obviates the need for paying for (or administering a self hosted) docker registry, and avoids the imperative push and pull model. Because a docker image is just another Nix package, you get distributed building, caching and signing for free. Also, as Nix caches intermediate packages builds, building a Docker image via Nix will likely be faster than letting Docker do it. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jpetazzo.github.io&#x2F;2020&#x2F;04&#x2F;01&#x2F;quest-minimal-docker-images-part-3&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; sums up the sentiment of this blog really well!&lt;&#x2F;li&gt;
&lt;li&gt;Using Nix as base image in multistage builds
Mixing both the worlds using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;nixos&#x2F;nix&quot;&gt;NixOS&lt;&#x2F;a&gt; as base image to write Dockerfiles is generally a comfortable approach.
Each build will run as an unprivileged user, that do not have any write access to any directory but its own build directory and the designated output Nix store paths.The network namespace helps the Nix builder to prevent a build process from accessing the network. In Nix, only builds that are so-called fixed output derivations (whose output hashes need to be known in advance) are allowed to download files from remote locations, because their output results can be verified.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Why you should consider using Nix in your build systems? Well you can even achieve what Vercel calls &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vercel.com&#x2F;docs&#x2F;monorepos&#x2F;remote-caching&quot;&gt;Remote Caching&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nix-flakes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix-flakes&quot; aria-label=&quot;Anchor link for: nix-flakes&quot;&gt;Nix Flakes&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I generally think of flakes in a docker container way (flakes run native on mac btw, Docker runs over VM)! Its said that &lt;code&gt;flakes are processors of Nix code&lt;&#x2F;code&gt;. This &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2020-05-25-flakes&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt; series is very informative to start working up the way! Sharing layers between flakes works better than Docker. Flakes can basically depend on other flakes! Unlike docker,  there are no cgroups or namespaces or VMs or anything with nix!&lt;&#x2F;p&gt;
&lt;p&gt;An excellent resource that I found for learning Nix was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ianthehenry.com&#x2F;posts&#x2F;how-to-learn-nix&#x2F;&quot;&gt;Ian Hnery’s How to learn Nix&lt;&#x2F;a&gt; diary! If you write a lot of Nix, you might also need to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2022-09-01-unit-test-your-nix-code&#x2F;&quot;&gt;unit test&lt;&#x2F;a&gt; it.&lt;&#x2F;p&gt;
&lt;p&gt;Its also an interesting read on how &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;supabase.com&#x2F;blog&#x2F;nix-postgres&quot;&gt;Supabase has now started to use Nix&lt;&#x2F;a&gt; being a well matured startup with a huge ecosystem around it.&lt;&#x2F;p&gt;
&lt;p&gt;Note that you need to enable ‘flakes’ and ‘commands’ by &lt;code&gt;experimental-features = nix-command flakes&lt;&#x2F;code&gt; in &lt;code&gt;~&#x2F;.config&#x2F;nix&#x2F;nix.conf&lt;&#x2F;code&gt; to use &lt;code&gt;nix build&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;raghavsood.com&#x2F;blog&#x2F;2024&#x2F;06&#x2F;14&#x2F;nix-flakes-fly&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt; shows how to start!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nix-flakes-with-rust&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix-flakes-with-rust&quot; aria-label=&quot;Anchor link for: nix-flakes-with-rust&quot;&gt;Nix flakes with Rust :)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Nix has a pretty bad reputation for its documentation, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jade.fyi&#x2F;blog&#x2F;flakes-arent-real&#x2F;&quot;&gt;Jade’s Nix guide to flakes&lt;&#x2F;a&gt; is an excellent writeup!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hoverbear.org&#x2F;blog&#x2F;a-flake-for-your-crate&#x2F;&quot;&gt;A Flake for your Crate&lt;&#x2F;a&gt; gives a great overview on how you can start using Nix with Rust. And &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;mmbfnj&#x2F;nixifying_a_rust_project&#x2F;&quot;&gt;nix-ifying a rust project&lt;&#x2F;a&gt; discussion is wholesome.&lt;&#x2F;p&gt;
&lt;p&gt;If you are also using WebAssembly in your Rust project, this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2022-09-22-rust-nix&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt; is quite helpful!&lt;&#x2F;p&gt;
&lt;p&gt;There is a fantastic &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;srid&#x2F;rust-nix-template&quot;&gt;template&lt;&#x2F;a&gt; to use!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nix-flakes-with-go&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix-flakes-with-go&quot; aria-label=&quot;Anchor link for: nix-flakes-with-go&quot;&gt;Nix flakes with Go&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-community&#x2F;gomod2nix&quot;&gt;gomodnix&lt;&#x2F;a&gt; and refer &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xeiaso.net&#x2F;blog&#x2F;nix-flakes-go-programs&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; blog to get started!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nix-flakes-with-ocaml&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix-flakes-with-ocaml&quot; aria-label=&quot;Anchor link for: nix-flakes-with-ocaml&quot;&gt;Nix flakes with OCaml&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tweag&#x2F;opam-nix&quot;&gt;opam-nix&lt;&#x2F;a&gt; with the corresponding &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2023-02-16-opam-nix&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt; to be a good enough starting point.&lt;&#x2F;p&gt;
&lt;p&gt;Nix has more binary packages than Homebrew does, so is generally faster as we don’t need to build much from the source, and some folks are literally using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jvns.ca&#x2F;blog&#x2F;2023&#x2F;02&#x2F;28&#x2F;some-notes-on-using-nix&#x2F;&quot;&gt;Nix as their Homebrew replacement&lt;&#x2F;a&gt;, and the only practical reasoning for it might be that its easier to setup a new machine with &lt;code&gt;flake.nix&lt;&#x2F;code&gt; compared to homebrew, basically having a single flake to maintain all the packages. You can even &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tweag.io&#x2F;blog&#x2F;2023-02-09-nixos-vm-on-macos&#x2F;&quot;&gt;run NixOS VM on Mac&lt;&#x2F;a&gt; now!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;take-it-easy-and-practically&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#take-it-easy-and-practically&quot; aria-label=&quot;Anchor link for: take-it-easy-and-practically&quot;&gt;Take it easy and practically&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To paint a simplified picture, the pieces that are useful to know are nixpkgs, and something like a Cargo.lock for Nix is flakes. By using flakes we can select a particular revision of the nixpkgs repository and every dependency we use will match what’s defined and built in it.&lt;&#x2F;p&gt;
&lt;p&gt;When you use it well :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You get rid  of works in my machine! despite running different distributions or OS, devs will have a consistent developer environment that very rarely breaks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zero-to-nix.com&#x2F;concepts&#x2F;incremental-builds&#x2F;#:~:text=Incremental%20builds%20are%20build%20processes%20that%20don&amp;#x27;t,all%20build%20results%20in%20the%20Nix%20store.&quot;&gt;You get awesome incremental build support. Nix prevents redundant work through content-addressable storage and aggressive caching.&lt;&#x2F;a&gt; Because every dependency (from specific versions of crates to the system LLVM&#x2F;glibc) is isolated into its own immutable Nix store path based on a cryptographic hash, modifying a single line of application code doesn’t force a re-download or recompilation of un-impacted third-party crates. Furthermore, teams can hook into distributed binary caches (like Cachix), if a coworker or a CI runner has already compiled a specific version of a crate or toolchain component, Nix simply downloads the pre-built binary instantly rather than burning CPU cycles compiling millions of lines of dependency code from scratch.&lt;&#x2F;li&gt;
&lt;li&gt;Because the package manager, compiler toolchains, and build system are tightly and declaratively integrated in Nix, tracking down regressions becomes significantly less painful than what you might be used to in traditional dev envs. As a real-life example, consider a scenario where a Rust-based project compiles cleanly under one version of the toolchain (e.g., Rust 1.75), but suddenly encounters a cryptic trait-solving error or unexpected LLVM code-generation panic when building with a newer nightly or stable release. In a traditional setup, attempting to bisect this kind of compiler or dependency regression requires manually installing multiple toolchains, altering global system paths, or wrestling with conflicting system libraries. With Nix and flakes, locking down or rolling back toolchain versions only takes a few lines of configuration. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lukego&#x2F;blog&#x2F;issues&#x2F;17&quot;&gt;By writing a short shell script wrapper or leveraging Nix’s ability to pin specific historical commits of nixpkgs, you can automate git bisect across entire dependency trees. When paired with git bisect run, Nix handles the heavy lifting—recreating an isolated, reproducible build environment for every single step in the commit history without bleeding state from your host system. In no time at all, you can drill down past thousands of package updates or compiler changes to isolate the exact PR responsible for the regression.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Because Nix enforces strict security hardening flags globally across its package ecosystem by default, such as stack protectors, position independent executables (PIE), and FORTIFY_SOURCE checks via its standard wrapper, it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;NixOS&#x2F;nixpkgs&#x2F;issues&#x2F;101979&quot;&gt;frequently surfaces latent bugs or undefined behavior in projects (especially those wrapping native C&#x2F;C++ libraries via cgo or FFI) that other package managers quietly bypass. Nix’s build environment (stdenv) goes out of its way to inject security hardening flags by default. It doesn’t just rely on upstream defaults; it actively wraps compilers (like GCC and Clang) to enforce these policies globally.&lt;&#x2F;a&gt;. This tendency of uncompromised safety can create friction in debugging though because these security flags are baked so deeply into Nix’s build wrappers, trying to do non-standard things, like building unoptimized code or working around strict buffer checks—requires precise configuration (hardeningDisable = [ “all” ] inside a Nix expression rather than a quick shell environment variable).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;nix-on-ci&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix-on-ci&quot; aria-label=&quot;Anchor link for: nix-on-ci&quot;&gt;Nix on CI&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since at the core of any CI, Nix is doing the same thing, there is no real vendor lock-in issue. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;garnix-io.github.io&#x2F;benchmarks&#x2F;&quot;&gt;This also means it should be possible to accurately benchmark these CIs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You will have to face a lot of errors when starting out with Nix, so be ready for being frustrated, like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discourse.nixos.org&#x2F;t&#x2F;weird-missing-nix-store-when-running-a-home-manager-rebuild&#x2F;37898&quot;&gt;this&lt;&#x2F;a&gt; :-]&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;You can do a lot of fancy stuff with Nix, but I just started out with Nix, like you!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These are a lot of resources that I shared, and I hope you will be a Nix ninja in no time if you go through all of this, so ALL THE BEST :)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Computer Science</title>
          <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/reads/cs/</link>
          <guid>https://harsh-ps-2003.github.io/reads/cs/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/reads/cs/">&lt;p&gt;Well, I used to hop around and read many CS books for passing my time in boring undergrad classes. It was fun, and I am not the best sort of a student. Here I am listing my favorite reads till now and, what and why would I pick them up for if I wanted to read again. They have helped me enjoy in the midst of boring lectures in IITK and I want to sincerely thank the authors for putting in the work. Also, I have shared the CS lectures I watched to grasp the concepts better so that people can have reference material and broader understanding of the interesting topics. The best way to learn these concepts is to implement some intriguing idea that you have while slowly and sensually reading these beauties!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The resources are in no particular order, I just enjoyed them, and you might also love them!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;intro-to-programming&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#intro-to-programming&quot; aria-label=&quot;Anchor link for: intro-to-programming&quot;&gt;Intro to Programming&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.norvig.com&#x2F;21-days.html&quot;&gt;Teach yourself programming in 10 years&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siboehm.com&#x2F;articles&#x2F;22&#x2F;tight-feedback-loops&quot;&gt;Becoming a Better Programmer by Tightening Feedback Loops&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pimbook.org&#x2F;&quot;&gt;A Programmer’s Introduction to Mathematics&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thesquareplanet.com&#x2F;blog&#x2F;coding-is-boring-engineering-isnt&#x2F;&quot;&gt;Coding is Boring, Engineering isn’t&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;Why-Machines-Learn-Elegant-Behind&#x2F;dp&#x2F;0593185749&quot;&gt;Why Machines Learn&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nand2tetris.org&#x2F;&quot;&gt;Building Modern Computers from first principles&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLnAxReCloSeTJc8ZGogzjtCtXl_eE6yzA&quot;&gt;How Computers Work&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;missing.csail.mit.edu&quot;&gt;MIT Missing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP62WVs95MNq3dQBqY2vGOtQ2&quot;&gt;Computational Structures&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=EKWGGDXe5MA&quot;&gt;Richard Feynman Computer Science Lecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;data-structures-and-algorithms&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#data-structures-and-algorithms&quot; aria-label=&quot;Anchor link for: data-structures-and-algorithms&quot;&gt;Data Structures and Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Introduction-Algorithms-fourth-Thomas-Cormen&#x2F;dp&#x2F;026204630X&#x2F;ref=sr_1_1?crid=2IHAGR7IHM0QX&amp;amp;keywords=introduction+to+algorithms&amp;amp;qid=1700927429&amp;amp;sprefix=introduction+%2Caps%2C349&amp;amp;sr=8-1&quot;&gt;Introduction to Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mimoza.marmara.edu.tr&#x2F;~msakalli&#x2F;cse706_12&#x2F;SkienaTheAlgorithmDesignManual.pdf&quot;&gt;The Algorithm Design Manual&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Grokking-Algorithms-illustrated-programmers-curious&#x2F;dp&#x2F;1617292230&#x2F;ref=sr_1_1?crid=12W6C5C7TSJ9S&amp;amp;keywords=grokking+algorithm&amp;amp;qid=1700928477&amp;amp;sprefix=grokking+%2Caps%2C373&amp;amp;sr=8-1&quot;&gt;Grokking Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&quot;&gt;Introduction to Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&quot;&gt;Design and Analysis of Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Just go &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;neetcode.io&#x2F;&quot;&gt;Neetcode&lt;&#x2F;a&gt; for those stupid Leetcode Medium&#x2F;Hards that you are going to get in your interviews. Leetcode preparation is unnecessary if you don’t want to work in Big Tech giants, but deep knowledge of Data Structures and Algorithms is crucial for crafting clever software!&lt;&#x2F;p&gt;
&lt;p&gt;If you are really into puzzles, Competitive Programming is a cool sport to be in! &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cses.fi&#x2F;book&#x2F;book.pdf&quot;&gt;CP Handbook is excellent to get started&lt;&#x2F;a&gt; along with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=oWgLjhM-6XE&amp;amp;list=PLrS21S1jm43igE57Ye_edwds_iL7ZOAG4&amp;amp;t&quot;&gt;this&lt;&#x2F;a&gt; lecture series. Try ICPC :) Not required for simple DSA rounds at tech companies though! Its fun, really fun once you get the hang of it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;computer-systems&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#computer-systems&quot; aria-label=&quot;Anchor link for: computer-systems&quot;&gt;Computer Systems&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Operating-System-Concepts-Abraham-Silberschatz&#x2F;dp&#x2F;1119800366&#x2F;ref=sr_1_1?crid=LU6CM1L1NM6D&amp;amp;keywords=operating+systems+concepts&amp;amp;qid=1700928693&amp;amp;sprefix=operating+systems+conce%2Caps%2C532&amp;amp;sr=8-1&quot;&gt;Operating System Concepts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Linux-Kernel-Development-Robert-Love&#x2F;dp&#x2F;0672329468&#x2F;ref=sr_1_1?crid=YVYXWIEK6RCB&amp;amp;keywords=linux+kernel+development&amp;amp;qid=1700928821&amp;amp;sprefix=linux+kernel+%2Caps%2C415&amp;amp;sr=8-1&quot;&gt;Linux Kernel Development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Linux-Programming-Interface-System-Handbook&#x2F;dp&#x2F;1593272200&#x2F;ref=sr_1_1?crid=6CDGSVTUTZ34&amp;amp;keywords=the+linux+programming+interface&amp;amp;qid=1700928931&amp;amp;sprefix=the+lin%2Caps%2C438&amp;amp;sr=8-1&quot;&gt;The Linux Programming Interface&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Advanced-Programming-UNIX-Environment-3rd&#x2F;dp&#x2F;0321637739&#x2F;ref=sr_1_1?crid=AU7DFIOPZOAC&amp;amp;keywords=advanced+programming+in+the+unix+environment&amp;amp;qid=1700929014&amp;amp;sprefix=advanced+program%2Caps%2C452&amp;amp;sr=8-1&quot;&gt;Advanced Programming in UNIX Environment&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.freebsd.org&#x2F;~lstewart&#x2F;articles&#x2F;cpumemory.pdf&quot;&gt;What every programmer should know about Memeory!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;scheme2006.cs.uchicago.edu&#x2F;11-ghuloum.pdf&quot;&gt;An incremental approach to Compiler construction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;willcrichton.net&#x2F;notes&#x2F;systems-programming&#x2F;&quot;&gt;What is Systems Programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.netanel.dev&#x2F;concurrency&quot;&gt;Intro to Concurrency&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.yoshuawuyts.com&#x2F;tree-structured-concurrency&#x2F;#what-is-structured-concurrency&quot;&gt;Tree Structured Concurrency&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;seven-concurrency-models&#x2F;9781941222737&#x2F;&quot;&gt;Seven Concurrency Models in Seven Weeks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&quot;&gt;Computer Systems Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PL9D558D49CA734A02&quot;&gt;Programming Paradigmns&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stevens.netmeister.org&#x2F;615&#x2F;&quot;&gt;NWU CS615&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stevens.netmeister.org&#x2F;631&#x2F;&quot;&gt;NWU CS361&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;norswap.com&#x2F;compilers&#x2F;&quot;&gt;UCL Compilers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLacuG5pysFbDQU8kKxbUh4K5c1iL5_k7k&quot;&gt;UMass CS377&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PL6535748F59DCA484&quot;&gt;Computer System Engineering&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PL5aMzERQ_OZ9j40DJNlsem2qAGoFbfwb4&quot;&gt;Concurrent Programming KAISTT CS341&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP63VIBQVWguXxZZi0566y7Wf&quot;&gt;Performance Engineering for Software Systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;networking&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#networking&quot; aria-label=&quot;Anchor link for: networking&quot;&gt;Networking&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Computer-Networks-5th-Andrew-Tanenbaum&#x2F;dp&#x2F;0132126958&#x2F;ref=sr_1_2?crid=1L210XMMZ5AF1&amp;amp;keywords=computer+networks&amp;amp;qid=1700929191&amp;amp;sprefix=computer+networks%2Caps%2C393&amp;amp;sr=8-2&quot;&gt;Computer Networks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;TCP-Illustrated-Protocols-Addison-Wesley-Professional&#x2F;dp&#x2F;0321336313&#x2F;ref=sr_1_1?crid=2KEG0E37QNX1I&amp;amp;keywords=tcp%2Fip+illustrated&amp;amp;qid=1700929218&amp;amp;sprefix=TCP%2F%2Caps%2C361&amp;amp;sr=8-1&quot;&gt;TCP&#x2F;IP Illustrated Vol 1&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLWl7jvxH18r3nnotitKkyAjq268PQGc0-&quot;&gt;NWU CS340&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;database-engineering&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#database-engineering&quot; aria-label=&quot;Anchor link for: database-engineering&quot;&gt;Database Engineering&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;seven-databases-in&#x2F;9781680505962&#x2F;&quot;&gt;Seven Databases in Seven Weeks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;Database-Systems-Complete-Book-2e&#x2F;dp&#x2F;933251867X?crid=1RRTN5MEG3XI3&amp;amp;keywords=Garcia+Molina&amp;amp;qid=1668967892&amp;amp;qu=eyJxc2MiOiIyLjQ3IiwicXNhIjoiMC4wMCIsInFzcCI6IjAuMDAifQ%3D%3D&amp;amp;s=books&amp;amp;sprefix=garcia+molina,stripbooks,212&amp;amp;sr=1-3&amp;amp;linkCode=sl1&amp;amp;tag=arpitbhayani-21&amp;amp;linkId=69e086c47419a7958ecbd0a251a9989c&amp;amp;language=en_IN&amp;amp;ref_=as_li_ss_tl&quot;&gt;Database Internals&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.scattered-thoughts.net&#x2F;writing&#x2F;against-sql&quot;&gt;Against SQL&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;riak.com&#x2F;assets&#x2F;bitcask-intro.pdf&quot;&gt;Bitcask&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;storage.googleapis.com&#x2F;pub-tools-public-publication-data&#x2F;pdf&#x2F;d84ab6c93881af998de877d0070a706de7bec6d8.pdf&quot;&gt;Monarch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLWl7jvxH18r0dflwRg3F51qQ8DV5ScQ1n&quot;&gt;NWU CS317&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLSE8ODhjZXjbj8BMuIrRcacnQh20hmY9g&quot;&gt;CMU CS625&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLSE8ODhjZXja7K1hjZ01UTVDnGQdx5v5U&quot;&gt;CMU CS721&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLSE8ODhjZXjY2xvwxuKjZT5qFH0sQga8_&quot;&gt;Seven Databases in Seven weeks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For real deep Database Enthusiasts &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@CMUDatabaseGroup&quot;&gt;CMU DB Group&lt;&#x2F;a&gt; is the GOLD STANDARD:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;scalable-architecture-and-distributed-systems&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#scalable-architecture-and-distributed-systems&quot; aria-label=&quot;Anchor link for: scalable-architecture-and-distributed-systems&quot;&gt;Scalable Architecture and Distributed Systems&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Distributed-Systems-Maarten-van-Steen&#x2F;dp&#x2F;9081540637&#x2F;ref=sr_1_2?crid=LB3MRDJ1HDC3&amp;amp;keywords=distributed+systems&amp;amp;qid=1700929287&amp;amp;sprefix=distributed+s%2Caps%2C448&amp;amp;sr=8-2&quot;&gt;Distributed Systems&lt;&#x2F;a&gt; and some cool texts from the TA &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thesquareplanet.com&#x2F;blog&#x2F;students-guide-to-raft&#x2F;&quot;&gt;Students guide to RAFT&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thesquareplanet.com&#x2F;blog&#x2F;instructors-guide-to-raft&#x2F;&quot;&gt;Instructors guide to RAFT&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.kezhuw.name&#x2F;2018&#x2F;03&#x2F;20&#x2F;A-step-by-step-approach-to-raft-consensus-algorithm&#x2F;&quot;&gt;A step by step guide to Raft Consensus Algorithm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Foundations-Scalable-Systems-Distributed-Architectures&#x2F;dp&#x2F;1098106067&#x2F;ref=sr_1_7?crid=LB3MRDJ1HDC3&amp;amp;keywords=distributed+systems&amp;amp;qid=1700929287&amp;amp;sprefix=distributed+s%2Caps%2C448&amp;amp;sr=8-7&quot;&gt;Designing Distributed Architectures&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Designing-Data-Intensive-Applications-Reliable-Maintainable&#x2F;dp&#x2F;1449373321&#x2F;ref=sr_1_1?crid=TE4GPBJHUN1W&amp;amp;keywords=designing+data-intensive+applications&amp;amp;qid=1700940392&amp;amp;sprefix=designing+data%2Caps%2C539&amp;amp;sr=8-1&quot;&gt;Designing Data Intensive Applications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3UQQ5NF&quot;&gt;Building Microservices: Designing Fine-Grained Systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.scattered-thoughts.net&#x2F;writing&#x2F;internal-consistency-in-streaming-systems&#x2F;&quot;&gt;Internal Consistency in Streaming Systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;static.googleusercontent.com&#x2F;media&#x2F;research.google.com&#x2F;en&#x2F;&#x2F;archive&#x2F;papers&#x2F;dapper-2010-1.pdf&quot;&gt;Dapper&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;storage.googleapis.com&#x2F;pub-tools-public-publication-data&#x2F;pdf&#x2F;10683a8987dbf0c6d4edcafb9b4f05cc9de5974a.pdf&quot;&gt;Zanzibar&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;conference&#x2F;hotos15&#x2F;hotos15-paper-mcsherry.pdf&quot;&gt;Scalability! But at what COST?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cidrdb.org&#x2F;cidr2023&#x2F;papers&#x2F;p83-yadav.pdf&quot;&gt;Flexiraft&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2010.09974&quot;&gt;Scalable Statistical Root Cause Analysis on App
Telemetry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;legacy&#x2F;event&#x2F;worlds06&#x2F;tech&#x2F;prelim_papers&#x2F;perl&#x2F;perl.pdf&quot;&gt;Google SSO&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2202.02071&quot;&gt;Alea-BFT&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2102.08325&quot;&gt;All you need is DAG&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2201.05677&quot;&gt;BullShark&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.in&#x2F;Patterns-Distributed-Systems-Addison-Wesley-Signature&#x2F;dp&#x2F;0138221987&quot;&gt;Patterns of Distributed Systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2204.03181&quot;&gt;A comprihensive review of BFT Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ceur-ws.org&#x2F;Vol-3478&#x2F;paper03.pdf&quot;&gt;A Survey and Comparison of Consistent Hashing Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;3712057&quot;&gt;Systems Correctness and Practices at AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cse.iitb.ac.in&#x2F;infolab&#x2F;Data&#x2F;Courses&#x2F;CS632&#x2F;2007&#x2F;Papers&#x2F;ratnasamy-CAN.pdf&quot;&gt;A Scalable CAN&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ferd.ca&#x2F;a-distributed-systems-reading-list.html&quot;&gt;Some short notes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLrw6a1wE39_tb2fErI4-WkMbsvGQk9_UB&quot;&gt;MIT 6.824&lt;&#x2F;a&gt; and go through assignments and labs as well &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;6.824&#x2F;general.html&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PL1iLu2CSC9EWlusZsVqXQ9BFg5jRRLzom&quot;&gt;Practical Distributed Systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLWl7jvxH18r0u5VRZsOjhghNXc_Ec4dZz&quot;&gt;NWU CS310&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@jordanhasnolife5163&quot;&gt;Jordan’s System Design videos&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;conference&#x2F;osdi20&#x2F;presentation&#x2F;yang&quot;&gt;A large scale analysis of hundreds of in-memory cache clusters at Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@distsysreadinggroup596&#x2F;videos&quot;&gt;Distributed Systems Reading Group&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ro2fU8_mr2w&quot;&gt;RAFT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLEGCF-WLh2RLOHv_xUGLqRts_9JxrckiA&quot;&gt;Foundations of Blockchain Protocols&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ikP5vHlW7nk&quot;&gt;Introduction to Distributed Consensus Algorithms&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=IvsANO0qZEg&quot;&gt;Choose API&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fly.io&#x2F;dist-sys&#x2F;&quot;&gt;Fly.io has a very cool distributes systems challenge!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;applied-cryptography&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#applied-cryptography&quot; aria-label=&quot;Anchor link for: applied-cryptography&quot;&gt;Applied Cryptography&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ee.stanford.edu&#x2F;~hellman&#x2F;publications&#x2F;24.pdf&quot;&gt;Diffie Hellman Protocol&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;serious-cryptography&#x2F;9781492067511&#x2F;&quot;&gt;Serious Cryptography&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.com&#x2F;Elliptic-Curves-Cryptography-Mathematics-Applications&#x2F;dp&#x2F;1420071467&quot;&gt;Elliptic Curves: Number Theory and Cryptography&lt;&#x2F;a&gt; (vitalik has a cool blogpost on it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@VitalikButerin&#x2F;exploring-elliptic-curve-pairings-c73c1864e627&quot;&gt;Exploring Elliptic Curve Pairings&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.au.dk&#x2F;~ivan&#x2F;Sigma.pdf&quot;&gt;Sigma Protocols&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adrianhamelink.com&#x2F;publication&#x2F;zk-report&#x2F;zk-report.pdf&quot;&gt;Understanding ZKP systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.cs.ucla.edu&#x2F;~rafail&#x2F;PUBLIC&#x2F;77.pdf&quot;&gt;ZK from SMPC&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.mit.edu&#x2F;sonka89&#x2F;www&#x2F;papers&#x2F;2017ygc.pdf&quot;&gt;Garbled Circuits&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.eecs.berkeley.edu&#x2F;~raluca&#x2F;oblix.pdf&quot;&gt;Oblix&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2013&#x2F;280.pdf&quot;&gt;Path ORAM&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;signal.org&#x2F;blog&#x2F;building-faster-oram&#x2F;&quot;&gt;How Signal Uses ORAM practically!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2021&#x2F;1280.pdf&quot;&gt;Snoopy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learn.0xparc.org&#x2F;&quot;&gt;Circom and Halo2&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vitalik.eth.limo&#x2F;general&#x2F;2019&#x2F;09&#x2F;22&#x2F;plonk.html&quot;&gt;Plonk&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.cs.ucla.edu&#x2F;~rafail&#x2F;PUBLIC&#x2F;34.pdf&quot;&gt;Replication is not Needed&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.iacr.org&#x2F;archive&#x2F;asiacrypt2010&#x2F;6477178&#x2F;6477178.pdf&quot;&gt;Constant-Size Commitments to Polynomials and
Their Applications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rareskills.io&#x2F;zk-book&quot;&gt;ZK-Book&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2023&#x2F;1478.pdf&quot;&gt;Succient Proofs and Linear Algebra&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@VitalikButerin&#x2F;zk-snarks-under-the-hood-b33151a013f6&quot;&gt;ZKSnarks under the hood&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.win.tue.nl&#x2F;~berry&#x2F;CryptographicProtocols&#x2F;LectureNotes.pdf&quot;&gt;Concise Notes when working with Bitcoin protocols&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2016&#x2F;663.pdf&quot;&gt;BBS+&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;risencrypto.github.io&#x2F;Groth16&#x2F;&quot;&gt;Groth16&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2013&#x2F;279.pdf&quot;&gt;Pinochio&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.iacr.org&#x2F;archive&#x2F;eurocrypt2000&#x2F;1807&#x2F;18070209-new.pdf&quot;&gt;Practical Threshold Signatures&lt;&#x2F;a&gt; and a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2020&#x2F;1390.pdf&quot;&gt;Survey on ECDSA Threshold signing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2020&#x2F;498.pdf&quot;&gt;Threshold ECDSA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2023&#x2F;397.pdf&quot;&gt;Hotstuff 2&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2105.11827&quot;&gt;Narhwal and Tusk&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2201.05677&quot;&gt;BullShark&lt;&#x2F;a&gt; paired with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2306.03058&quot;&gt;Shoal&lt;&#x2F;a&gt; combined with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2310.14821&quot;&gt;Mysticeti&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2205.06837&quot;&gt;Latency Reduction in P2P networks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2017&#x2F;974.pdf&quot;&gt;Obscuro&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cseweb.ucsd.edu&#x2F;classes&#x2F;fa02&#x2F;cse208&#x2F;&quot;&gt;Advanced Cryptography notes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.cs.georgetown.edu&#x2F;jthaler&#x2F;ProofsArgsAndZK.pdf&quot;&gt;Proofs, Arguments and ZK&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.zkdocs.com&quot;&gt;ZKDocs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;b-chiang&#x2F;protocol-reading-list&quot;&gt;Various crypto protocols&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2019&#x2F;550.pdf&quot;&gt;Spartan&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;static1.squarespace.com&#x2F;static&#x2F;5fdbb09f31d71c1227082339&#x2F;t&#x2F;5ff394720493bd28278889c6&#x2F;1609798774687&#x2F;PairingsForBeginners.pdf&quot;&gt;Pairings for Begineers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2024&#x2F;692.pdf&quot;&gt;Blink&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLEAYkSg4uSQ3gN6P13YQLb-JxiwDWsFs8&quot;&gt;Introduction to General Cryptography&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLgKuh-lKre139cwM0pjuxMa_YVzMeCiTf&quot;&gt;Applied Cryptography&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP61EZllk7zwgvPbI4kbnKhWz&quot;&gt;Advanced Topics in Cryptography&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@thebiuresearchcenteronappl8783&#x2F;playlists&quot;&gt;Winter School to Cryptography&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zkiap.com&#x2F;&quot;&gt;ZKIAP&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLS01nW3RtgoqqvF39f11ncNAClgSLPlXD&quot;&gt;Programming ZKPs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=PdfDZIwuZm0&quot;&gt;Multiparty Threshold ECDSA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=usUoTN8f9M8&quot;&gt;ZKBoo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=3RWyVGwG9U8&amp;amp;t=307s&amp;amp;pp=ygUJdHJlZSBvcmFt&quot;&gt;ORAM&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tE57KBK_GW4&quot;&gt;Pure Rust ECC&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@fhe_org&#x2F;playlists&quot;&gt;Fully Homomorphic Encryptions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;ai-ml&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-ml&quot; aria-label=&quot;Anchor link for: ai-ml&quot;&gt;AI&#x2F;ML&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Lectures:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PL49CF3715CB9EF31D&quot;&gt;Linear Algebra&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP62EaLLH92E_VCN4izBKK6OE&quot;&gt;Matrix Calculus for ML and beyond&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP61MdtwGTqZA0MreSaDybji8&quot;&gt;Probabilistic Systems Analysis and Applied Probability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUl4u3cNGP619EG1wp0kT-7rDE_Az5TNd&quot;&gt;Introduction to Computational Thinking and Data Science&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtube.com&#x2F;playlist?list=PLoROMvodv4rMiGQp3WXShtMGgzqpfVfbU&amp;amp;si=YcK9DPmQUawE2jrv&quot;&gt;Intro to Machine Learning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLgPbN3w-ia_PeT1_c5jiLW3RJdR7853b9&quot;&gt;Deep Learning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLxdnSsBqCrrHo2EYb_sMctU959D-iPybT&quot;&gt;Introduction to Optimization&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLvJ08ASPN6JPOsN1O91T0uVA-U7jfYBKU&quot;&gt;Convex Optimizations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtube.com&#x2F;playlist?list=PLmd_zeMNzSvRRNpoEWkVo6QY_6rR3SHjp&amp;amp;si=EvQVc1VEYKQyX-aJ&quot;&gt;Differential Privacy in Machine Learning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLSrTvUm384I9PV10koj_cqit9OfbJXEkq&quot;&gt;MLSys Seminar&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLJkYEExhe7rYFkBIB2U5pf_RWzYnFLj7r&quot;&gt;AI for Sciences and Engineering&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLuD_SqLtxSdW5aasHsFTNw_MrZrtu5tZ3&quot;&gt;Physics Informed Machine Learning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Reads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.deeplearningbook.org&#x2F;&quot;&gt;Deep Learning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;programming-languages&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#programming-languages&quot; aria-label=&quot;Anchor link for: programming-languages&quot;&gt;Programming Languages&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Books:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;&quot;&gt;Rust Atomics and Locks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-for-rustaceans.com&#x2F;&quot;&gt;Rust for Rustaceans&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;concurrency-in-go&#x2F;9781491941294&#x2F;&quot;&gt;Concurrency in Go&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nimprogrammingbook.com&#x2F;book&#x2F;nimprogramming_molokai.pdf&quot;&gt;A Gentle Introduction to Nim&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;random&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#random&quot; aria-label=&quot;Anchor link for: random&quot;&gt;Random&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;~shmat&#x2F;shmat_oak08netflix.pdf&quot;&gt;Robust De-anonymization of Large Sparse Datasets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;No you don’t have to know all this to be called a great engineer (I am not even a software engineer when writing this!). These are simply a compilation of things I got particularly interested in and simply loved consuming.&lt;&#x2F;p&gt;
&lt;p&gt;All the best!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Philosophy</title>
          <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/reads/philosophy/</link>
          <guid>https://harsh-ps-2003.github.io/reads/philosophy/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/reads/philosophy/">&lt;p&gt;When I am talking about Philosophy, don’t confuse it with Theology, I have a love affair with life not with beliefs!&lt;&#x2F;p&gt;
&lt;p&gt;Here are some of my favorite books:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Prophet&lt;&#x2F;li&gt;
&lt;li&gt;One Hundred Poems of Kabir&lt;&#x2F;li&gt;
&lt;li&gt;Escape from Freedom&lt;&#x2F;li&gt;
&lt;li&gt;Sophies World&lt;&#x2F;li&gt;
&lt;li&gt;Love (Stendhal)&lt;&#x2F;li&gt;
&lt;li&gt;The Monarchy of Fear&lt;&#x2F;li&gt;
&lt;li&gt;Dialogues concerning Natural Religion&lt;&#x2F;li&gt;
&lt;li&gt;Confessions of an Economic Hitman&lt;&#x2F;li&gt;
&lt;li&gt;The Idiot&lt;&#x2F;li&gt;
&lt;li&gt;Existentialism is Humanism&lt;&#x2F;li&gt;
&lt;li&gt;Notes from the Underground&lt;&#x2F;li&gt;
&lt;li&gt;Age of Reason&lt;&#x2F;li&gt;
&lt;li&gt;Good Fortune and the Myth of Meritocracy&lt;&#x2F;li&gt;
&lt;li&gt;Stories we live by&lt;&#x2F;li&gt;
&lt;li&gt;The Great Escape&lt;&#x2F;li&gt;
&lt;li&gt;Blind Owl&lt;&#x2F;li&gt;
&lt;li&gt;The Mind-Body Problem&lt;&#x2F;li&gt;
&lt;li&gt;Labyrinths&lt;&#x2F;li&gt;
&lt;li&gt;No Exit&lt;&#x2F;li&gt;
&lt;li&gt;The Burnout Society&lt;&#x2F;li&gt;
&lt;li&gt;The Lost Daughter&lt;&#x2F;li&gt;
&lt;li&gt;The Origins of Political Order&lt;&#x2F;li&gt;
&lt;li&gt;The Essays&lt;&#x2F;li&gt;
&lt;li&gt;The Feminine Mystique&lt;&#x2F;li&gt;
&lt;li&gt;The Invention of Solitude&lt;&#x2F;li&gt;
&lt;li&gt;How to Lie with Statistics&lt;&#x2F;li&gt;
&lt;li&gt;A Fine Balance&lt;&#x2F;li&gt;
&lt;li&gt;Einsteins Dreams&lt;&#x2F;li&gt;
&lt;li&gt;The Upside of Irrationality&lt;&#x2F;li&gt;
&lt;li&gt;Famine, Affluence and Morality&lt;&#x2F;li&gt;
&lt;li&gt;A Life’s Work: On becoming a Mother&lt;&#x2F;li&gt;
&lt;li&gt;Then we came to the end&lt;&#x2F;li&gt;
&lt;li&gt;The Tyranny of Merit&lt;&#x2F;li&gt;
&lt;li&gt;The Book of Mirdad&lt;&#x2F;li&gt;
&lt;li&gt;Several Short Sentences About Writing&lt;&#x2F;li&gt;
&lt;li&gt;Too loud a Solitude&lt;&#x2F;li&gt;
&lt;li&gt;To the Lighthouse&lt;&#x2F;li&gt;
&lt;li&gt;Enlightenment Is Your Nature&lt;&#x2F;li&gt;
&lt;li&gt;The Lessons of History&lt;&#x2F;li&gt;
&lt;li&gt;The Rights of Man&lt;&#x2F;li&gt;
&lt;li&gt;The Surrender Experiment&lt;&#x2F;li&gt;
&lt;li&gt;Wild Problems&lt;&#x2F;li&gt;
&lt;li&gt;The Plague&lt;&#x2F;li&gt;
&lt;li&gt;The Brothers Karamazov&lt;&#x2F;li&gt;
&lt;li&gt;The Letters to a young poet&lt;&#x2F;li&gt;
&lt;li&gt;Mans Search for Meaning&lt;&#x2F;li&gt;
&lt;li&gt;The Gardener and the Carpenter&lt;&#x2F;li&gt;
&lt;li&gt;The Essential Rumi&lt;&#x2F;li&gt;
&lt;li&gt;Affective Neuroscience&lt;&#x2F;li&gt;
&lt;li&gt;The Cynic Philosophers: from Diogenese to Julian&lt;&#x2F;li&gt;
&lt;li&gt;On The Shortness of Life&lt;&#x2F;li&gt;
&lt;li&gt;Die with Zero&lt;&#x2F;li&gt;
&lt;li&gt;Penguin Nausea&lt;&#x2F;li&gt;
&lt;li&gt;The Myth of Sisyphus&lt;&#x2F;li&gt;
&lt;li&gt;Either&#x2F;Or&lt;&#x2F;li&gt;
&lt;li&gt;All About Love&lt;&#x2F;li&gt;
&lt;li&gt;Infinite Jest&lt;&#x2F;li&gt;
&lt;li&gt;The Structure of Scientific Revolutions&lt;&#x2F;li&gt;
&lt;li&gt;Sun and Steel&lt;&#x2F;li&gt;
&lt;li&gt;Steppenwolf&lt;&#x2F;li&gt;
&lt;li&gt;The Sound and the Fury&lt;&#x2F;li&gt;
&lt;li&gt;Why I am an Atheist&lt;&#x2F;li&gt;
&lt;li&gt;My Experiments with Truth&lt;&#x2F;li&gt;
&lt;li&gt;Tuesdays with morrie&lt;&#x2F;li&gt;
&lt;li&gt;The Defining Decade&lt;&#x2F;li&gt;
&lt;li&gt;Siddhartha&lt;&#x2F;li&gt;
&lt;li&gt;The Stranger&lt;&#x2F;li&gt;
&lt;li&gt;The Catcher in the Rye&lt;&#x2F;li&gt;
&lt;li&gt;Courage to be Disliked&lt;&#x2F;li&gt;
&lt;li&gt;The case against education&lt;&#x2F;li&gt;
&lt;li&gt;1984&lt;&#x2F;li&gt;
&lt;li&gt;The Revolt of the Elites&lt;&#x2F;li&gt;
&lt;li&gt;East of Eden&lt;&#x2F;li&gt;
&lt;li&gt;Lolita&lt;&#x2F;li&gt;
&lt;li&gt;Brave New World&lt;&#x2F;li&gt;
&lt;li&gt;The Grapes of Wrath&lt;&#x2F;li&gt;
&lt;li&gt;The Human Zoo&lt;&#x2F;li&gt;
&lt;li&gt;Atlas Shrugged&lt;&#x2F;li&gt;
&lt;li&gt;The Politics of Reality: Essays in Feminist Theory&lt;&#x2F;li&gt;
&lt;li&gt;On the Genealogy of Morality&lt;&#x2F;li&gt;
&lt;li&gt;Pointers to Non Duality&lt;&#x2F;li&gt;
&lt;li&gt;Tao Te Ching&lt;&#x2F;li&gt;
&lt;li&gt;The Pictures of Dorian Gray&lt;&#x2F;li&gt;
&lt;li&gt;On Earth We are Briefly Gorgeous&lt;&#x2F;li&gt;
&lt;li&gt;Flow&lt;&#x2F;li&gt;
&lt;li&gt;Dream Machine&lt;&#x2F;li&gt;
&lt;li&gt;The Tail End&lt;&#x2F;li&gt;
&lt;li&gt;The Tell Tail Heart&lt;&#x2F;li&gt;
&lt;li&gt;Crime and Punishment&lt;&#x2F;li&gt;
&lt;li&gt;The Life of Alexander the Great&lt;&#x2F;li&gt;
&lt;li&gt;Beyond Good and Evil&lt;&#x2F;li&gt;
&lt;li&gt;The Right to Oblivion: Privacy and the Good Life&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These have been a wonderful reads till now and have exposed me to a new me!&lt;&#x2F;p&gt;
&lt;p&gt;Some wonderful talks :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;tab:https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ji5_MqicxSo&amp;amp;t=40s&quot;&gt;Achieving your childhood dreams&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;tab:https:&#x2F;&#x2F;youtube.com&#x2F;playlist?list=PL30C13C91CFFEFEA6&amp;amp;si=gZcJBmOPKFTUYpy5&quot;&gt;Justice&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;tab:https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UMGl30B5HpQ&quot;&gt;Mass Immigration&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;tab:https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=wLn28DrSF68&amp;amp;t&quot;&gt;Building a Life&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Startups</title>
          <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/reads/startups/</link>
          <guid>https://harsh-ps-2003.github.io/reads/startups/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/reads/startups/">&lt;p&gt;The collection of most impactful startup execution texts I have gone through. Whether you want to work on an indie company or a scaled startups, these are some good reads for general perspectives :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Only the Paranoid Survive&lt;&#x2F;li&gt;
&lt;li&gt;Start small, stay small&lt;&#x2F;li&gt;
&lt;li&gt;Remote: Office not required&lt;&#x2F;li&gt;
&lt;li&gt;The Managers Path&lt;&#x2F;li&gt;
&lt;li&gt;Company of One&lt;&#x2F;li&gt;
&lt;li&gt;Zero to One&lt;&#x2F;li&gt;
&lt;li&gt;Staff Engineers&lt;&#x2F;li&gt;
&lt;li&gt;GenAI and engineering teams&lt;&#x2F;li&gt;
&lt;li&gt;Fundraising&lt;&#x2F;li&gt;
&lt;li&gt;High Output Management&lt;&#x2F;li&gt;
&lt;li&gt;Blitzscaling&lt;&#x2F;li&gt;
&lt;li&gt;The Startup of You&lt;&#x2F;li&gt;
&lt;li&gt;4-hour workweek&lt;&#x2F;li&gt;
&lt;li&gt;The Hard Thing About Hard Things&lt;&#x2F;li&gt;
&lt;li&gt;Shoe Dog&lt;&#x2F;li&gt;
&lt;li&gt;The Checklist Manifesto&lt;&#x2F;li&gt;
&lt;li&gt;The Lean Startup&lt;&#x2F;li&gt;
&lt;li&gt;Play Nice But Win&lt;&#x2F;li&gt;
&lt;li&gt;What got you here, wont take you there&lt;&#x2F;li&gt;
&lt;li&gt;No Rules Rules&lt;&#x2F;li&gt;
&lt;li&gt;Choosing Startup Life&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Spent my summers exploring Bitcoin 💸</title>
          <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://harsh-ps-2003.github.io/writes/sob/</link>
          <guid>https://harsh-ps-2003.github.io/writes/sob/</guid>
          <description xml:base="https://harsh-ps-2003.github.io/writes/sob/">&lt;p&gt;Anyone who is into investing their hard earned money knows about Bitcoin, it’s one thing that has gained significant traction over the years due to its phenomenal returns and dependability. I was too enthusiastic about it, but wanted to accumulate some technical knowledge before pouring in my money! I dont trust, I verify :) Then I stumbled upon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.summerofbitcoin.org&#x2F;&quot;&gt;Summer of Bitcoin&lt;&#x2F;a&gt; which was a summer internship for university students around globe to learn about Bitcoin and earn a stipend for their OSS work after learning! Now thats what I can being at the right place at the right time! Less than 1% applications are accepted, its extremely competitive and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harsh-ps-2003&#x2F;haikyu&quot;&gt;challenge&lt;&#x2F;a&gt; that I had to solve was mind numbing to say the least, especially because I had no knowledge of Bitcoin technical details, so I learnt on the go (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;programming-bitcoin&#x2F;9781492031482&#x2F;&quot;&gt;Programming Bitcoin&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.oreilly.com&#x2F;library&#x2F;view&#x2F;grokking-bitcoin&#x2F;9781617294648&#x2F;?_gl=1*cceq5o*_ga*MTMzMDQxNzY2MC4xNzIwNzg4Nzgz*_ga_092EL089CH*MTcyMDg2NDM1OC40LjEuMTcyMDg2NDM5Ny4yMS4wLjA.&quot;&gt;Grokking Bitcoin&lt;&#x2F;a&gt; were a big help)!
Luckily, I got selected to work on an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;harsh-ps-2003&#x2F;escrow&quot;&gt;Escrow Module&lt;&#x2F;a&gt; based on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jbonneau.com&#x2F;doc&#x2F;GBGN17-FC-physical_escrow.pdf&quot;&gt;paper&lt;&#x2F;a&gt; for the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fedimint.org&#x2F;&quot;&gt;Fedimint&lt;&#x2F;a&gt; ecosystem, under the Summer of Bitcoin 2024, and I must say, I got really humbled and inspired looking at those Staff Software Engineers punching OSS code left, right and center! I mean the maintainers build at the speed of light :). I felt like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hJbjLaCJd6g&quot;&gt;this&lt;&#x2F;a&gt; and I am grateful for the experience! I was aware of the some plugin&#x2F;module architectures due to my work at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jenkins.io&#x2F;&quot;&gt;Jenkins&lt;&#x2F;a&gt;. The whole idea is to asyncronyously extend the backend without tinkering with the core, giving the devs the flexibility to empower the ecosystem! The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=G4iclApJL0c&quot;&gt;Fedimint Primer&lt;&#x2F;a&gt; is a great starting point for anyone to have an overview! &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2306.12783v1&quot;&gt;This&lt;&#x2F;a&gt; paper is also a great point to start understanding things conceptually!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-s-fedimint&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-fedimint&quot; aria-label=&quot;Anchor link for: what-s-fedimint&quot;&gt;What’s Fedimint?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine you and a group of friends want to create a small, private digital cash system, a bit like a community bank or a shared digital piggy bank. You want it to be secure and trustworthy, even if not everyone in your group is available 24&#x2F;7, or (in a more serious scenario) if one person tries to cheat.&lt;&#x2F;p&gt;
&lt;p&gt;How do you all agree on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Who has how much money?&lt;&#x2F;li&gt;
&lt;li&gt;Which transactions are valid?&lt;&#x2F;li&gt;
&lt;li&gt;The order in which transactions happened?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is where Federations and Consensus come in. They provide the framework for a group of participants to collectively manage a system and agree on its state.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine the Fedimint federation is your local community bank. The Fedimint Client is like your personal banking app for that specific bank. It’s the software you run on your phone or computer that lets you interact with the federation’s services.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-s-fedimint-technically&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-fedimint-technically&quot; aria-label=&quot;Anchor link for: what-s-fedimint-technically&quot;&gt;What’s Fedimint technically?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Fedimint represents a sophisticated approach to scaling Bitcoin and enhancing privacy through &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=alyYNIX0m3o&quot;&gt;federated chaumian e-cash&lt;&#x2F;a&gt;. Its modular architecture, robust consensus mechanism, and Lightning Network integration make it a powerful tool for building decentralized financial applications&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A Fedimint Federation is a group of server operators, called Guardians - trusted members of the federation, who run the Fedimint software (fedimintd). A majority of these Guardians need to be honest and reliable. The &lt;code&gt;fedimintd&lt;&#x2F;code&gt; serves as the main consensus code for processing transactions and providing a REST API. It’s the heart of the Fedimint server implementation.&lt;&#x2F;p&gt;
&lt;p&gt;Fedimint uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cardinal-cryptography.github.io&#x2F;AlephBFT&#x2F;what_is_aleph_bft.html&quot;&gt;AlephBFT consensus algorithm&lt;&#x2F;a&gt; to achieve agreement among federation members about the state of system like :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Which Transactions are valid&lt;&#x2F;li&gt;
&lt;li&gt;The order in which these transactions occurred&lt;&#x2F;li&gt;
&lt;li&gt;The current state of any Modules (like the digital cash module)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The result of this consensus process is a shared ledger.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; fedimint-core&#x2F;src&#x2F;epoch.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; All the items that may be produced during a consensus epoch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Eq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PartialEq&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Hash&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Encodable&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Decodable&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ConsensusItem&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Threshold sign the epoch history for verification via the API&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Transaction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Transaction&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Any data that modules require consensus on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Module&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ModuleConsensusItem&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... other variants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A &lt;code&gt;ConsensusItem&lt;&#x2F;code&gt; can be a Transaction or data specific to a Module (like an e-cash minting operation).&lt;&#x2F;p&gt;
&lt;p&gt;How a transaction is agreed upon :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------+     +-----------+     +-----------+     +-----------+     +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  User  |     | GuardianA |     | GuardianB |     | GuardianC |     | Consensus Algorithm |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+--------+     +-----------+     +-----------+     +-----------+     +----------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                 |                 |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  Submit Proposal (e.g., tx)       |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  -------------------------------&amp;gt; |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   | Share Proposal  |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   | --------------&amp;gt; |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   | Share Proposal  |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   | -------------------------------&amp;gt;       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 | Share Proposal       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 | -----------------&amp;gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |      &amp;lt;------------- Guardians broadcast proposed items to each other ----&amp;gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                            [ AlephBFT Ordering &amp;amp; Agreement Phase ]         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                 &amp;lt;----------- Guardians exchange messages -------------&amp;gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                 &amp;lt;--- Agree on order and validity of proposed items ---&amp;gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                      Finalize a batch of ordered items = SessionOutcome   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                 &amp;lt;------------- SessionOutcome Generated --------------&amp;gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                       Guardians sign SessionOutcome with threshold keys   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                      &amp;lt;------------- Sign Outcome (2&#x2F;3+) -------------&amp;gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                  &amp;lt;--- SignedSessionOutcome assembled from signatures ---&amp;gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                   |                 |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                   SignedSessionOutcome recorded by all Guardians          |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                      ---------------- Ledger Updated ----------------     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On the server-side (fedimintd), a component often referred to as the “Consensus Engine” manages this whole process. It takes items submitted for consensus, works with AlephBFT to order them, and then processes the agreed-upon items.&lt;&#x2F;p&gt;
&lt;p&gt;Fedimint Client is responsible for managing secrets, assets, building transactions, talking to federation, tracking operations, using modeules, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Fedimint has an SDK in place in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;tree&#x2F;master&#x2F;fedimint-client&quot;&gt;fedimint-client&lt;&#x2F;a&gt; for providing high-level operations for interacting with the Fedimint federation using a Dynamic api client &lt;code&gt;DynGlobalApi&lt;&#x2F;code&gt; and client side data, initialized by &lt;code&gt;ClientModuleInit&lt;&#x2F;code&gt; which will be implemented by each module. It provides utilities for building and submitting transactions and uses a state machine (client state machines are for writing client side logic that the module might need so that they can be executed in idempotent steps that can get persisted in the database. This is so that everything work even if a client device is being constantly being shut-down abruptly etc.&lt;&#x2F;p&gt;
&lt;p&gt;When you send e-cash or perform other operations that change ownership of assets, the client builds a Transaction. This transaction will contain:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Inputs: What you’re spending (e.g., some of your e-cash notes).&lt;&#x2F;li&gt;
&lt;li&gt;Outputs: What’s being created (e.g., new e-cash notes for the recipient, and potentially change notes for yourself).&lt;&#x2F;li&gt;
&lt;li&gt;Signatures: Cryptographic proof that you authorized the spending of your inputs.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Typically inputs and output of a given transaction have client side state machine. Sometimes some other state machines are needed as well.
Typically a transaction is submitted to federation, and client needs to do something afterward - e.g. wait for the transaction to get accepted or rejected and do some corresponding things afterwards.
The states in the state machine can be thought of “snapshots” saved into the database. The SDK also handles logging and error handling.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Client&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Configuration specific to this federation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tokio&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;RwLock&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ClientConfig&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Your client&amp;#39;s local database&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    db&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Database&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Your unique root secret for this federation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    root_secret&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DerivableSecret&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; API for talking to the federation guardians&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; api&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DynGlobalApi&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Registry of client modules (e-cash, LN, etc.)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;crate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; modules&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ClientModuleRegistry&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Executor for running state machines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    executor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Executor&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Task group for managing background tasks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    task_group&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; TaskGroup&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... other fields&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;tree&#x2F;master&#x2F;modules&quot;&gt;modules&lt;&#x2F;a&gt; are the lifeline of fedimint architecture! The Mint module (implementing federated e-cash), Wallet module (handling on-chain deposits and withdrawing) and the Lightening module (integration with the Lightening Network allowing users to send and receive Lightning payments using their e-cash balance) serve as the core modules on which the Fedimint ecosystem functions. The developers can extend the &lt;code&gt;fedimint-core&lt;&#x2F;code&gt; by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=T454R_3P8GA&quot;&gt;adding more modules&lt;&#x2F;a&gt;, like I am doing right now :)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Add modules you want to use (e.g., e-cash, Lightning)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; client_builder.with_module(MintClientInit); &#x2F;&#x2F; For e-cash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; client_builder.with_module(LightningClientInit); &#x2F;&#x2F; For Lightning&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; client_handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; client_builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;my_root_secret&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; federation_config&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; None&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; api_secret &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This join process initializes your client for that specific federation.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;finalize_and_submit_transaction&lt;&#x2F;code&gt; function is a core part of the Client. It takes a partially built transaction, works with modules to complete it (e.g., by adding e-cash inputs to pay for it and creating change outputs), and then sets up a state machine (TxSubmissionStatesSM) to manage the actual submission to the federation and track its acceptance.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;ClientHandle&lt;&#x2F;code&gt; manages the lifecycle of the Client. When the last ClientHandle is dropped (goes out of scope), it triggers a shutdown process for the client, stopping its background tasks and releasing resources. This is important for clean program termination. Most of your interactions will be through this handle.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; fedimint-client&#x2F;src&#x2F;client&#x2F;handle.rs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ClientHandle&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    inner&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How client interacts with Federation :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;mermaid&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-----------+         +----------------+         +--------------+         +--------------------------+         +---------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| User App  |         | FedimintClient |         | E-cash Module|         | Federation API (Guardian)|         | Client Local DB     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-----------+         +----------------+         +--------------+         +--------------------------+         +---------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  I want to deposit BTC! |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | ----------------------&amp;gt; |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |  User wants to deposit  |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         | ----------------------&amp;gt; |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | Request deposit address   |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | -----------------------&amp;gt; |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | &amp;lt;-----------------------  |  Returns BTC address           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |  Got deposit address    |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         | &amp;lt;---------------------- |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | [Starts StateMachine to   |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |  watch deposit address]   |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  Send BTC to [address]  |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | &amp;lt;---------------------- |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  (User sends BTC)       |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |     Later, after confirmation...                           |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | Has deposit confirmed?    |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | -----------------------&amp;gt; |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | &amp;lt;-----------------------  | Yes, here&amp;#39;s new e-cash notes  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | Store e-cash notes        |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         | -----------------------&amp;gt; |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |  Deposit successful     |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         | &amp;lt;---------------------- |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  Deposit complete!      |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | &amp;lt;---------------------- |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                         |                         |                           |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Every Fedimint module has two parts that work together:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ClientModule: This defines how your client application interacts with the features of that specific module. It lives within your Fedimint Client.&lt;&#x2F;li&gt;
&lt;li&gt;ServerModule: This defines how the federation’s guardians manage the state and rules for that module. It lives within the fedimintd server software run by the guardians.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The ClientModule for e-cash (often called MintClientModule) is responsible for things like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Knowing how to construct a request to get new e-cash notes.&lt;&#x2F;li&gt;
&lt;li&gt;Storing your e-cash notes securely in the client’s database.&lt;&#x2F;li&gt;
&lt;li&gt;Knowing how to select the e-cash notes you own when you want to spend them.&lt;&#x2F;li&gt;
&lt;li&gt;Creating the “input” part of a Transaction that proves you own the notes you’re spending.&lt;&#x2F;li&gt;
&lt;li&gt;Understanding how to interpret responses from the federation related to e-cash.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The ServerModule for e-cash (often called MintServerModule) runs on each guardian’s server. It’s responsible for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Defining the rules for valid e-cash notes.&lt;&#x2F;li&gt;
&lt;li&gt;Issuing the cryptographic signatures (blind signatures) that create new e-cash notes when funds are deposited.&lt;&#x2F;li&gt;
&lt;li&gt;Verifying the “input” part of a Transaction when someone tries to spend e-cash notes. This includes checking for valid signatures and preventing double-spends.&lt;&#x2F;li&gt;
&lt;li&gt;Keeping track of which notes have already been spent (managing the module’s state).&lt;&#x2F;li&gt;
&lt;li&gt;Participating in the Federation &amp;amp; Consensus process to agree on the validity of e-cash transactions.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; fedimint-server-core&#x2F;src&#x2F;lib.rs (Simplified)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;apply&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;async_trait_maybe_send&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ServerModule&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Sized&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... other types ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This module&amp;#39;s contribution to the next consensus proposal.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; consensus_proposal&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        dbtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DatabaseTransaction&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... ConsensusItem type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Process a consensus item agreed upon by the federation.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process_consensus_item&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        dbtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DatabaseTransaction&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        consensus_item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... ConsensusItem type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        peer_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PeerId&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; anyhow&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Verify and process a transaction input related to this module.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process_input&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        dbtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DatabaseTransaction&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;c&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... Input type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        in_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; InPoint&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;InputMeta&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... InputError type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Verify and process a transaction output related to this module.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; process_output&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        dbtx&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DatabaseTransaction&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... Output type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        out_point&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OutPoint&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TransactionItemAmount&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... OutputError type ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... other methods like verify_input, audit ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The spend flow :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-----------+     +----------------+     +---------------------+     +----------------------------+     +------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;|  Your App |     | FedimintClient |     | Mint Client Module  |     | Federation API (Guardians) |     | Mint Server Module     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+-----------+     +----------------+     +---------------------+     +----------------------------+     +------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  Spend 100 sats    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | -----------------&amp;gt; |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |  Prepare to spend 100  |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | ---------------------&amp;gt; |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        | Selects e-cash notes     |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        | from local DB            |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |  Input data (note+proof)                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | &amp;lt;--------------------- |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |  Build Transaction T (includes e-cash input)      |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | ------------------------------------------------&amp;gt; |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | Verify e-cash input from T     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | -----------------------------&amp;gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | Check signature + spent flag   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |   +-------------------------+  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |   |   Input Valid?          |  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |   +-------------------------+  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |           &#x2F;         \         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |       Yes           No        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |        |              |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | Mark note as      Reject due |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | spent (consensus)  to double |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                        spend |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |        |              |       |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          | &amp;lt;--------------------        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |  Input OK           Input Invalid! |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | &amp;lt;--------------------- |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | Transaction Confirmed                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | -----------------------------&amp;gt;               |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | Spend Successful                             |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | &amp;lt;----------------------------                |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |   [Else Branch: Double Spend] |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |                          |  Transaction Rejected         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | &amp;lt;------------------------------------------------ |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |  Spend failed (Double Spend)                 |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | -----------------------------&amp;gt;               |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    |                        |  Revert note to DB       |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                    | ---------------------&amp;gt; |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | Spend Failed (Double Spend)                  |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     | &amp;lt;----------------------------                |                          |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The module creation process is eased via the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint-custom-modules-example&quot;&gt;custom-module-example template&lt;&#x2F;a&gt;. You can play with the module in a nerdy way using &lt;code&gt;just mprocs&lt;&#x2F;code&gt; inside the nix environment, just create some users and have fun with your module!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;db&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#db&quot; aria-label=&quot;Anchor link for: db&quot;&gt;DB&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It uses &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;tree&#x2F;master&#x2F;fedimint-rocksdb&quot;&gt;RocksDB&lt;&#x2F;a&gt; as the high-performance embedded key-value storage engine (can be easily integrated into the Fedimint application without requiring a separate database server) due to its high performance, especially for write-heavy workloads (which is crucial for a financial system like Fedimint) and fast reads, optimistic transactions and more! Fedimint has customized RocksDB options to suit its specific needs, such as setting write buffer size (performance optimization), use custom prefix-keys and recovery mode. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rockset.com&#x2F;blog&#x2F;how-we-use-rocksdb-at-rockset&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; is sweet to go deeper into RocksDB!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nix&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nix&quot; aria-label=&quot;Anchor link for: nix&quot;&gt;Nix&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first hurdle I faced before contributing was to get myself comfortable with the reproducible &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nixos.org&#x2F;&quot;&gt;Nix&lt;&#x2F;a&gt; environments (due to my low storage on 256GB macbook air, I had to &lt;code&gt;nix-collect-garbage -d&lt;&#x2F;code&gt; a lot, deeply painful, but Nix does make the developer experience outstanding). Nix is extensively used in the Fedimint project for managing the development environment (Flakebox) , building the project, and deploying Fedimint instances, cross-compilations in CI builds, and more ofcourse! Also, debugging rust in Nix was an exciting adventure! I wrote &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;harsh-ps-2003.bearblog.dev&#x2F;nix&#x2F;&quot;&gt;Starting to pick up Nix a bit&lt;&#x2F;a&gt; as a collection of resources that I loved!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;monitoring-and-observibility&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#monitoring-and-observibility&quot; aria-label=&quot;Anchor link for: monitoring-and-observibility&quot;&gt;Monitoring and Observibility&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Fedimint implements a robust metrics collection and exposure mechanism using Prometheus. Each module has its own set of metrics. The global collection of metrics happens in a static, lazy-initialized &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;blob&#x2F;e3ff9e3dea330fb071e4de4d55307e6a7ba53719&#x2F;fedimint-metrics&#x2F;src&#x2F;lib.rs#L20&quot;&gt;Registery&lt;&#x2F;a&gt; using a custom macro system. It utilizes various Prometheus metric types, including Histogram, IntCounter, Gauge, and their vector counterparts. An new thing is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;blob&#x2F;e3ff9e3dea330fb071e4de4d55307e6a7ba53719&#x2F;fedimint-metrics&#x2F;src&#x2F;lib.rs#L23&quot;&gt;predefined buckets&lt;&#x2F;a&gt; for amount-related histograms, chosen to cover a wide range of Bitcoin amounts, from fractions of a satoshi to 100 million satoshis (1 BTC). Fedimint exposes its metrics through an HTTP endpoint, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;blob&#x2F;e3ff9e3dea330fb071e4de4d55307e6a7ba53719&#x2F;fedimint-metrics&#x2F;src&#x2F;lib.rs#L53&quot;&gt;implemented&lt;&#x2F;a&gt; using the Axum. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;blob&#x2F;e3ff9e3dea330fb071e4de4d55307e6a7ba53719&#x2F;fedimintd&#x2F;src&#x2F;fedimintd.rs#L499&quot;&gt;As soon as the the fedimintd process starts, the metrics server also starts&lt;&#x2F;a&gt;. Metrics are updated when the transaction is successful maintaining consistency between DB and metrics. It supports OpenTelemetry integration with Jaeger for distributed tracing. These can easily be visualized in Grafana!&lt;&#x2F;p&gt;
&lt;p&gt;The load testing tool measures and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;blob&#x2F;3c0ffa1256d731220a7d1e217c8cf2fb85b6af0e&#x2F;fedimint-load-test-tool&#x2F;src&#x2F;main.rs#L1190&quot;&gt;compares performance metrics&lt;&#x2F;a&gt; across different runs, tracking performance changes over time over different configurations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;performance-analysis&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#performance-analysis&quot; aria-label=&quot;Anchor link for: performance-analysis&quot;&gt;Performance Analysis&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tracing-chrome&#x2F;latest&#x2F;tracing_chrome&#x2F;&quot;&gt;Chrome tracing&lt;&#x2F;a&gt; is implemented for integration tests (&lt;code&gt;devimint&lt;&#x2F;code&gt; is used for local fedimint environments) in Fedimint, generating a JSON file named &lt;code&gt;trace-{UNIX_TIME}.json&lt;&#x2F;code&gt; in the current working directory which can be opened and visualized using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;perfetto.dev&#x2F;&quot;&gt;Perfetto&lt;&#x2F;a&gt;. This setup allows developers to perform detailed performance analysis of integration tests by visualizing the execution timeline, identifying bottlenecks, and understanding the flow of operations within the Fedimint system during test runs. Also, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;tree&#x2F;master&#x2F;fedimint-load-test-tool&quot;&gt;fedimint-load-test-tool&lt;&#x2F;a&gt; is for performance testing for federation, scalability assessment, gateway integration testing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wasm-tests&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wasm-tests&quot; aria-label=&quot;Anchor link for: wasm-tests&quot;&gt;Wasm Tests&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&#x2F;tree&#x2F;master&#x2F;fedimint-wasm-tests&quot;&gt;Wasm tests&lt;&#x2F;a&gt; are crucial for ensuring that Fedimint’s client-side operations work correctly in a browser environment, which is essential for web-based wallets or applications using Fedimint. This is a really cool thing that I saw implemented in a Bitcoin project for the first time!&lt;&#x2F;p&gt;
&lt;p&gt;It also has fuzz testing but thats quite standard, so wont write about it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Damn, the repository is sooo big, it will take me an eternity writing all about it, it would be best for you to check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fedimint&#x2F;fedimint&quot;&gt;repository&lt;&#x2F;a&gt; yourself, don’t forget to star it!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-got-rustier&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-got-rustier&quot; aria-label=&quot;Anchor link for: i-got-rustier&quot;&gt;I got rustier :)&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Naturally, was curious on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=DnT-LUQgc7s&quot;&gt;why folks are using Rust at the first place!&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.lambdaclass.com&#x2F;please-stop-drinking-the-rust-kool-aid&#x2F;&quot;&gt;especially in blockchain&lt;&#x2F;a&gt;. Was pretty excited. Played with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redixhumayun.github.io&#x2F;async&#x2F;2024&#x2F;08&#x2F;05&#x2F;async-runtimes.html&quot;&gt;async Rust&lt;&#x2F;a&gt;, and explored &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=lJ3NC-R3gSI&quot;&gt;journey of Rust to async programming&lt;&#x2F;a&gt;. I got intimidated by the codebase initially due to extremely complex and long Rust Types but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=uh9i3be2wIE&quot;&gt;this&lt;&#x2F;a&gt; tutorial helped me a ton! I went deep into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=7_o-YRxf_cc&amp;amp;t=0s&quot;&gt;visualizingn memory layout of Rust Datatypes&lt;&#x2F;a&gt; just for fun! Learnt about Static and Dynamic dispatcher! You know, its &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2021&#x2F;rust-data-structures-with-circular-references&quot;&gt;slightly harder to write some Data Structures in Rust!&lt;&#x2F;a&gt; My mentor suggested me to look into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2023&#x2F;12&#x2F;07&#x2F;rust-design-axioms&#x2F;&quot;&gt;Rust Design Axioms&lt;&#x2F;a&gt; and in general better Rust patterns and techniques to improve maintainability and overall code quality for which I referred to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=vqavdUGKeb4&quot;&gt;this&lt;&#x2F;a&gt; talk. The most dreaded thing that I had to face was the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;blog.ezyang.com&#x2F;2013&#x2F;12&#x2F;two-bugs-in-the-borrow-checker-every-rust-developer-should-know-about&#x2F;&quot;&gt;Rust’s overconservative Borrow Checker&lt;&#x2F;a&gt;. Explored &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xeiaso.net&#x2F;blog&#x2F;serde-precompiled-stupid&#x2F;&quot;&gt;rust compile times&lt;&#x2F;a&gt; as well!
Got exposed to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;48350087&#x2F;how-do-i-conditionally-compile-for-webassembly-in-rust&quot;&gt;conditional compilation between native and WASM targets&lt;&#x2F;a&gt; and handling runtime differences. Hah! just got &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLFdNoRgzggbr7tkQsO4VrF1UGy0ji9sZl&quot;&gt;gently pushed to Advanced Rust!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Got initiated to think about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dpc.pw&#x2F;posts&#x2F;how-i-structure-my-apps-in-rust-and-other-languages&#x2F;&quot;&gt;structuring my code and thinking about the system design&lt;&#x2F;a&gt;. Also got &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dpc.pw&#x2F;posts&#x2F;improve-your-code-reviews&#x2F;&quot;&gt;some advise on code reviews&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The best Rust tutorial that I could find was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLDbRgZ0OOEpUkWDGqp91ODn0dk7LPBAUL&quot;&gt;this&lt;&#x2F;a&gt;!
&lt;em&gt;The more I use Rust, the more impressed I am!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Laughingly, during the internship, instead of doing Test Driven Development, I ended up doing Error Driven Development ;(&lt;&#x2F;p&gt;
&lt;h3 id=&quot;thank-you&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#thank-you&quot; aria-label=&quot;Anchor link for: thank-you&quot;&gt;Thank you!&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The fedimint community was exceptionally warm and welcoming to the new contributors. Special thanks to the maintainers &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;kodylow&quot;&gt;KodyLow&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;maan2003&quot;&gt;Manmeet&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dpc&quot;&gt;David&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;justinmoon&quot;&gt;Justin&lt;&#x2F;a&gt; and my mentor &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shaurya947&quot;&gt;Shaurya&lt;&#x2F;a&gt; for making the experience a memorable one! I will cherish it forever, they initiated me to Bitcoin!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bitcoin-stuff-i-am-excited-about-in-the-near-future&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bitcoin-stuff-i-am-excited-about-in-the-near-future&quot; aria-label=&quot;Anchor link for: bitcoin-stuff-i-am-excited-about-in-the-near-future&quot;&gt;Bitcoin stuff I am excited about in the near future!&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Really pumped up on how &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crysp.uwaterloo.ca&#x2F;software&#x2F;frost&#x2F;&quot;&gt;FROST signature schemes&lt;&#x2F;a&gt; paired with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ZcashFoundation&#x2F;frost&#x2F;issues&#x2F;519&quot;&gt;Dynamic and Verifiable Secret Sharing&lt;&#x2F;a&gt; will make the multi-sig wallet experience buttery smooth! The most awaited would be to have backup wallets! So Cool, it will redefine the Bitcoin experience for the users while also improving security :) Also excited to see the use of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adiabat.github.io&#x2F;dlc.pdf&quot;&gt;Conditional Payments using Discrete Log Contract&lt;&#x2F;a&gt; suitable in cases where 2 mutually distrusting parties bet on the results! Also, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bitvm.org&#x2F;bitvm_bridge.pdf&quot;&gt;BitVM&lt;&#x2F;a&gt; is a heart-throb! And &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=zLMvlLgv66Y&quot;&gt;work on Bitcoin L2 is also cool&lt;&#x2F;a&gt;, and I think &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;starkware.co&#x2F;blog&#x2F;scaling-bitcoin-for-mass-use&#x2F;&quot;&gt;StarkNet might very realistically scale Bitcoin with Ethereum&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=QquvK-gMOFk&quot;&gt;My future generation will inherit a superior money, Bitcoin!&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wanna-contribute-to-bitcoins-glory&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wanna-contribute-to-bitcoins-glory&quot; aria-label=&quot;Anchor link for: wanna-contribute-to-bitcoins-glory&quot;&gt;Wanna Contribute to Bitcoins Glory?&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;danielabrozzoni.com&#x2F;posts&#x2F;contributing-to-oss&#x2F;&quot;&gt;This&lt;&#x2F;a&gt; is a solid starter advise for anyone new! Get
accustomed to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bitcoindevphilosophy.com&#x2F;&quot;&gt;Bitcoin Development Philosophy&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
