<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://manojkumar-github.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://manojkumar-github.github.io/" rel="alternate" type="text/html" /><updated>2026-06-14T10:44:46-05:00</updated><id>https://manojkumar-github.github.io/feed.xml</id><title type="html">Xariv Engineering</title><subtitle>Practical engineering write-ups and case studies from Xariv — how we build systems, solve hard problems, and ship reliable software.</subtitle><author><name>Xariv</name></author><entry><title type="html">Networking Bottlenecks in Large-Scale Mixture-of-Experts (MoE) Inference</title><link href="https://manojkumar-github.github.io/networking-bottlenecks-large-scale-moe-inference/" rel="alternate" type="text/html" title="Networking Bottlenecks in Large-Scale Mixture-of-Experts (MoE) Inference" /><published>2026-06-14T00:00:00-05:00</published><updated>2026-06-14T00:00:00-05:00</updated><id>https://manojkumar-github.github.io/networking-bottlenecks-large-scale-moe-inference</id><content type="html" xml:base="https://manojkumar-github.github.io/networking-bottlenecks-large-scale-moe-inference/"><![CDATA[<blockquote>
  <p><strong>Architecture Study.</strong> This is a hypothetical system study. The numbers, topology,
and traffic patterns are illustrative and do not describe any specific employer or
production deployment. The goal is to reason from first principles about a class of
problem that recurs across large sparse-model serving systems.</p>
</blockquote>

<h2 id="1-executive-summary">1. Executive summary</h2>

<p>We studied a hypothetical inference platform serving an AI-powered <strong>search answer
generation</strong> experience — the kind that returns a synthesized, cited answer rather
than a list of links — at a scale of <strong>billions of requests per day</strong> with a
sub-second p99 latency target.</p>

<p>The model is a <strong>235B-parameter Mixture-of-Experts (MoE)</strong> decoder served across a
fleet of NVIDIA H100 GPUs. Our initial capacity model assumed GPU compute would be
the dominant bottleneck, so the scaling plan was simple: add GPUs, get throughput.</p>

<p>It did not work. Doubling GPUs from 128 to 256 returned roughly <strong>1.2×</strong> more
throughput, not 2×. Profiling showed the GPUs were frequently <em>idle, waiting</em> — not
on compute, but on the <strong>expert-routing traffic</strong> that MoE generates on every decode
step. The bottleneck had quietly moved from the silicon into the <strong>network fabric</strong>.</p>

<p>This article walks the investigation end to end: the business framing, the baseline
assumptions, the benchmarks, the profiling, the root cause, and the production-grade
mitigations — topology design, communication-library tuning, fleet placement, and
monitoring — with an emphasis on the <strong>NVIDIA GPU and networking stack</strong> (NVLink,
NVSwitch, InfiniBand, NCCL, NVSHMEM, GPUDirect RDMA, and DCGM).</p>

<h2 id="2-business-context">2. Business context</h2>

<p>Before any architecture, the business shape of the problem dictates the constraints.</p>

<p>An answer-generation search surface has an unusual cost profile:</p>

<ul>
  <li><strong>Volume is enormous and spiky.</strong> Billions of queries a day, with diurnal peaks.</li>
  <li><strong>Latency is a product feature.</strong> Users abandon slow answers; the p99, not the
mean, is what the SLO protects.</li>
  <li><strong>Cost per answer must be predictable.</strong> Margins on free, ad-adjacent, or
flat-rate enterprise search are thin, so utilization has to stay high.</li>
</ul>

<p>A <strong>dense</strong> model large enough to give good answers is economically painful here:
every token activates every parameter, so cost scales with full model size on every
request. <strong>MoE</strong> is attractive precisely because it decouples <em>capacity</em> from
<em>per-token compute</em> — a 235B-parameter model might activate only ~20B parameters per
token by routing each token to a small number of specialized experts. On paper, you
get the quality of a large model at the compute cost of a small one.</p>

<p>The catch — and the subject of this study — is that the routing which makes MoE cheap
in FLOPs makes it expensive in <strong>communication</strong>.</p>

<h2 id="3-architectural-overview">3. Architectural overview</h2>

<p><img src="/assets/img/moe-architecture.svg" alt="Request lifecycle across the inference platform" />
<em>Figure 1. The request lifecycle. Compute stages look local; the expert-parallel group hides a network underneath.</em></p>

<p>A request flows through a frontend router (auth, routing, SLO enforcement), into a
<strong>continuous batcher</strong> that interleaves prefill and decode work to keep GPUs busy,
and into the <strong>MoE decoder</strong>. The decoder runs attention locally, then a <strong>top-k
gating</strong> network selects which experts each token should visit.</p>

<p>Because the 235B parameters do not fit on one GPU, experts are sharded across the
fleet using <strong>expert parallelism (EP)</strong>: each GPU owns a subset of experts. When a
token is routed to an expert living on a <em>different</em> GPU — which is the common case —
its activations must be sent there and the result sent back. That movement is the
hidden network we will spend the rest of the article on.</p>

<h2 id="4-baseline-assumptions">4. Baseline assumptions</h2>

<p>Writing down what we <em>expected</em> before measuring is what makes the surprise legible.</p>

<p>We assumed:</p>

<ol>
  <li><strong>Attention compute dominates</strong> the decode step.</li>
  <li><strong>GPU utilization is the throughput ceiling</strong> — saturate the GPUs and you win.</li>
  <li><strong>Networking scales linearly</strong> — more nodes, proportionally more fabric bandwidth.</li>
  <li><strong>Expert-routing overhead is small</strong> relative to FFN compute.</li>
</ol>

<p>Every one of these turned out to be wrong at scale, in ways that compounded.</p>

<h2 id="5-benchmark-environment">5. Benchmark environment</h2>

<p>We built a realistic but hypothetical test bed:</p>

<table>
  <thead>
    <tr>
      <th>Component</th>
      <th>Configuration</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>GPUs</td>
      <td>64 → 512 NVIDIA H100 (80 GB SXM)</td>
    </tr>
    <tr>
      <td>Node</td>
      <td>8× H100, NVSwitch all-to-all, ~900 GB/s NVLink per GPU</td>
    </tr>
    <tr>
      <td>Inter-node fabric</td>
      <td>NVIDIA Quantum-2 InfiniBand, NDR 400 Gb/s (ConnectX-7)</td>
    </tr>
    <tr>
      <td>Parallelism</td>
      <td>Expert Parallel = 16, Tensor Parallel = 8</td>
    </tr>
    <tr>
      <td>Comms</td>
      <td>NCCL with GPUDirect RDMA</td>
    </tr>
    <tr>
      <td>Workload</td>
      <td>decode-heavy, short prompts, streaming answers</td>
    </tr>
  </tbody>
</table>

<p>The workload matters: answer generation is <strong>decode-heavy</strong>. Decode emits one token
at a time, so each step moves <em>small</em> tensors very frequently. Hold that thought — it
is the crux of the root cause.</p>

<h2 id="6-first-benchmark-results">6. First benchmark results</h2>

<p>We scaled the fleet with the model and traffic mix held constant and measured
relative throughput:</p>

<table>
  <thead>
    <tr>
      <th style="text-align: right">GPUs</th>
      <th style="text-align: right">Expected (linear)</th>
      <th style="text-align: right">Measured</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: right">64</td>
      <td style="text-align: right">1.0×</td>
      <td style="text-align: right">1.0×</td>
    </tr>
    <tr>
      <td style="text-align: right">128</td>
      <td style="text-align: right">2.0×</td>
      <td style="text-align: right">1.7×</td>
    </tr>
    <tr>
      <td style="text-align: right">256</td>
      <td style="text-align: right">4.0×</td>
      <td style="text-align: right">2.1×</td>
    </tr>
    <tr>
      <td style="text-align: right">512</td>
      <td style="text-align: right">8.0×</td>
      <td style="text-align: right">2.25×</td>
    </tr>
  </tbody>
</table>

<p><img src="/assets/img/moe-scaling.svg" alt="Throughput vs GPU count, ideal versus measured" />
<em>Figure 2. Throughput decouples from GPU count. The widening gap is the cost of communication, not a shortage of compute.</em></p>

<p>The curve flattens hard. By 512 GPUs we were paying for 8× the hardware to get a
little over 2× the work. GPU utilization counters, meanwhile, looked <em>fine</em> on
average — which is exactly how this class of bug hides.</p>

<h2 id="7-investigation-phase">7. Investigation phase</h2>

<h3 id="71-gpu-analysis">7.1 GPU analysis</h3>

<p>We started where the assumptions pointed. Using <strong>Nsight Systems</strong> to capture a
timeline and <strong>DCGM</strong> for fleet-wide counters:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Per-rank timeline with NVTX ranges and NCCL/cuDNN traces</span>
nsys profile <span class="nt">-t</span> cuda,nvtx,nccl <span class="nt">-o</span> decode_step <span class="se">\</span>
  <span class="nt">--capture-range</span><span class="o">=</span>cudaProfilerApi python serve_decode.py
</code></pre></div></div>

<p>The kernels were healthy: attention and FFN GEMMs hit expected SM occupancy, HBM
bandwidth was nowhere near saturated, and there were no obvious stalls <em>inside</em> the
compute kernels. Average SM utilization looked acceptable — but the timeline told a
different story: long, recurring <strong>gaps between kernels</strong>, aligned across ranks. The
GPUs were synchronized in their <em>idleness</em>.</p>

<h3 id="72-router-analysis">7.2 Router analysis</h3>

<p>Next we instrumented the gating network and logged per-expert token counts. Routing
was <strong>not uniform</strong>. With learned top-2 gating, a handful of experts attracted
disproportionate traffic:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>expert_load (tokens/step, normalized):
  E0:1.0  E1:0.9  ...  E17:6.1  ...  E63:0.4
</code></pre></div></div>

<p>Expert 17 was receiving roughly <strong>6× the average</strong> load. Token routing in trained MoE
models is rarely balanced in practice; popularity is data-dependent and drifts over
time. A hot expert means a hot <em>destination</em> on the network.</p>

<h3 id="73-network-analysis">7.3 Network analysis</h3>

<p>The aligned idle gaps plus a hot destination pointed straight at the fabric. We read
InfiniBand port and switch counters and NCCL transport stats:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">NCCL_DEBUG</span><span class="o">=</span>INFO <span class="nv">NCCL_DEBUG_SUBSYS</span><span class="o">=</span>NET python serve_decode.py
perfquery <span class="nt">-x</span>            <span class="c"># IB port counters: xmit/rcv data, wait, congestion</span>
</code></pre></div></div>

<p>The fabric showed the signature of <strong>congestion</strong>: rising switch-buffer occupancy,
<strong>PFC pause</strong> frames (RoCE) / congestion-control throttling (InfiniBand), and ECN
marks concentrated on the links feeding the hot experts. The story had begun.</p>

<h2 id="8-the-hidden-cost-of-moe">8. The hidden cost of MoE</h2>

<p>The decode loop most engineers picture is <em>compute</em>: attention → FFN → next token.
The loop that actually governs throughput is <em>communication</em>:</p>

<p><img src="/assets/img/moe-comm-flow.svg" alt="Per-token MoE communication flow with two all-to-all collectives" />
<em>Figure 3. Every decode step contains two network collectives — dispatch and combine — repeated for every output token.</em></p>

<p>Each decode step performs <strong>two all-to-all collectives</strong>:</p>

<ol>
  <li><strong>Dispatch</strong> — every GPU sends each token to the GPU that owns its selected expert.</li>
  <li><strong>Combine</strong> — every GPU sends the expert outputs back to the token’s origin.</li>
</ol>

<p>In NVIDIA’s stack these are typically realized as a <strong>grouped sequence of
<code class="language-plaintext highlighter-rouge">ncclSend</code>/<code class="language-plaintext highlighter-rouge">ncclRecv</code> calls</strong> (an all-to-all-v pattern) so that each rank can send
different amounts to different peers — because, as we saw, the distribution is uneven.
Intra-node hops ride <strong>NVLink/NVSwitch</strong>; inter-node hops ride <strong>InfiniBand with
GPUDirect RDMA</strong>, so the NIC reads and writes GPU memory directly without bouncing
through the CPU.</p>

<p>The critical property: in <strong>decode</strong>, each of these transfers is <em>small</em> (one token’s
hidden state per expert) but <em>extremely frequent</em> (twice per token). That makes the
all-to-all <strong>latency- and message-rate-bound, not bandwidth-bound</strong>. You can have
terabytes per second of fabric bandwidth sitting idle while throughput collapses,
because the limiter is <em>how many small messages per second</em> the fabric and NICs can
push — and how long the <em>slowest</em> one takes.</p>

<h2 id="9-why-expert-parallelism-creates-network-hotspots">9. Why expert parallelism creates network hotspots</h2>

<p>Four effects compound:</p>

<p><strong>Hot experts.</strong> Learned routing concentrates traffic on a few experts. Their host
GPUs become network destinations far above the average.</p>

<p><strong>Incast.</strong> In a single step, many source GPUs send to the <em>same</em> hot expert at the
<em>same</em> time. Their flows converge on one switch egress port, overflowing its buffer.</p>

<p><img src="/assets/img/moe-incast.svg" alt="Incast onto a hot expert overloading a switch port" />
<em>Figure 4. Incast: synchronized convergence onto a popular expert saturates a single port, triggering pause/ECN and stalling its senders.</em></p>

<p><strong>Collective amplification.</strong> One routing decision per token fans out into many small
transfers across the fabric. Sparse routing turns a compute choice into a
communication storm.</p>

<p><strong>Tail latency dominance.</strong> A collective is a barrier: the step cannot finish until
<em>every</em> transfer completes. One congested port — the slowest expert’s link — gates
the entire step. This is why average utilization looked healthy while throughput
suffered: <strong>the tail, not the mean, sets the pace.</strong></p>

<h2 id="10-scaling-analysis">10. Scaling analysis</h2>

<p>Zoom out and the geometry gets worse. A flat all-to-all over N GPUs creates on the
order of <strong>N² small inter-node flows</strong>. As N grows:</p>

<ul>
  <li><strong>At ~100 GPUs</strong>, NVLink keeps most traffic node-local; the fabric copes.</li>
  <li><strong>At ~1,000 GPUs</strong>, east-west (server-to-server) traffic dominates and <strong>spine-leaf
pressure</strong> becomes the limiter; per-flow bandwidth shrinks as flows multiply.</li>
  <li><strong>At ~10,000 GPUs</strong>, locality and topology <em>are</em> the design. Without
rack-/rail-aware placement, the bisection bandwidth and switch buffering simply
cannot absorb a synchronized N² incast.</li>
</ul>

<p>The takeaway: beyond a node, <strong>throughput is a function of the network topology and
the traffic’s locality</strong>, not of the GPU count.</p>

<h2 id="11-mitigations-and-tradeoffs">11. Mitigations and tradeoffs</h2>

<p>There is no single fix. We treated this as a portfolio of changes, each a tradeoff.</p>

<p><strong>Topology-aware expert placement.</strong> Place frequently co-activated experts within the
same NVLink island so their traffic never touches the fabric.
<em>Pro:</em> removes inter-node hops for the hottest paths. <em>Con:</em> placement must track
drifting routing distributions; stale placement decays.</p>

<p><strong>Expert replication for hot experts.</strong> Replicate the few popular experts across
nodes and load-balance across replicas to break the incast.
<em>Pro:</em> directly attacks the hotspot. <em>Con:</em> costs memory and adds a consistency/
routing-decision surface.</p>

<p><strong>Hierarchical all-to-all.</strong> Aggregate token transfers <em>within</em> a node over NVLink,
do a <strong>single</strong> fat inter-node exchange over InfiniBand, then scatter within the
destination node — instead of every GPU talking to every remote GPU directly.</p>

<p><img src="/assets/img/moe-hierarchical-a2a.svg" alt="Flat versus hierarchical all-to-all" />
<em>Figure 5. Hierarchical all-to-all collapses many tiny inter-node messages into few large ones, trading message rate for bandwidth — the right trade for a fabric that is message-rate-bound.</em></p>

<p><em>Pro:</em> converts a message-rate problem into a bandwidth problem the fabric is good at;
libraries such as <strong>NVSHMEM</strong>-based dispatch and modern expert-parallel comm kernels
exploit exactly this. <em>Con:</em> added kernel complexity and an extra on-node staging step.</p>

<p><strong>Topology-aware / adaptive routing in the fabric.</strong> Enable InfiniBand <strong>adaptive
routing</strong> and tune congestion control (DCQCN/ECN/PFC for RoCE) so converging flows
spread across paths rather than piling onto one.
<em>Pro:</em> mitigates incast without code changes. <em>Con:</em> tuning is workload-specific and
can interact badly with bursty traffic if misconfigured.</p>

<p><strong>Rail-optimized network design.</strong> Home each GPU’s NIC to its own <em>rail</em> (leaf), so an
all-to-all maps onto parallel, independent rails instead of one shared bottleneck.
NCCL’s <strong>PXN</strong> (PCI × NVLink) path keeps traffic rail-local.</p>

<p><img src="/assets/img/moe-rail-topology.svg" alt="Rail-optimized spine-leaf topology with NVLink islands" />
<em>Figure 6. Rail-optimized topology. GPU index i always egresses on rail i, so synchronized all-to-all traffic is spread across rails by construction.</em></p>

<p><em>Pro:</em> structural — the topology itself prevents a class of hotspot. <em>Con:</em> it is a
data-center build decision, hard to retrofit.</p>

<p><strong>Communication-library tuning.</strong> NCCL exposes the knobs that decide whether small
collectives are fast:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Prefer low-latency protocols for small decode messages</span>
<span class="nb">export </span><span class="nv">NCCL_PROTO</span><span class="o">=</span>LL128
<span class="c"># Keep transfers on GPUDirect RDMA; never bounce via host</span>
<span class="nb">export </span><span class="nv">NCCL_NET_GDR_LEVEL</span><span class="o">=</span>PHB
<span class="c"># Pin to the rail-local HCA and raise channel count for parallelism</span>
<span class="nb">export </span><span class="nv">NCCL_IB_HCA</span><span class="o">=</span>mlx5
<span class="nb">export </span><span class="nv">NCCL_MIN_NCHANNELS</span><span class="o">=</span>8
<span class="c"># Allow PXN rail-local routing</span>
<span class="nb">export </span><span class="nv">NCCL_PXN_DISABLE</span><span class="o">=</span>0
</code></pre></div></div>

<p><em>Pro:</em> large gains for zero hardware cost. <em>Con:</em> values are topology- and
shape-specific; the right setting at 128 GPUs may be wrong at 512.</p>

<p><strong>Note on SHARP.</strong> NVIDIA’s in-network reduction (<strong>SHARP</strong>) accelerates <em>reductions</em>
such as the all-reduce in tensor-parallel layers, but it does <strong>not</strong> accelerate the
all-to-all that MoE dispatch/combine relies on. It is worth enabling for the parts of
the model that reduce — just don’t expect it to fix the MoE hotspot.</p>

<h2 id="12-the-bigger-insight">12. The bigger insight</h2>

<blockquote>
  <p>In large-scale sparse models, the dominant bottleneck is increasingly <strong>communication,
not computation</strong>. The more we sparsify and distribute a model to save FLOPs, the more
we spend on moving activations — and that spending lands on the network.</p>
</blockquote>

<p>Said differently: MoE trades compute for communication. That trade is usually a win,
but it relocates the bottleneck from a place we instrument well (the GPU) to a place we
instrument poorly (the fabric, the tail, the incast). The engineering discipline that
matters at scale is <strong>communication-aware system design</strong>.</p>

<h2 id="13-implications-for-future-ai-systems">13. Implications for future AI systems</h2>

<p>The same physics will shape what comes next:</p>

<ul>
  <li><strong>Trillion-parameter MoE</strong> pushes more experts onto more nodes — more all-to-all,
more incast, more dependence on topology.</li>
  <li><strong>Agentic systems</strong> chain many model calls; their tail latency is a <em>product</em> of
per-call tails, so per-call network jitter compounds.</li>
  <li><strong>Distributed KV-cache and memory disaggregation</strong> add yet another east-west traffic
class competing for the same fabric.</li>
  <li><strong>AI datacenter design</strong> increasingly co-designs the model-parallel strategy with
the network topology, rather than treating them as separate layers.</li>
</ul>

<h2 id="14-production-profiling-fleet-and-monitoring">14. Production: profiling, fleet, and monitoring</h2>

<p>A benchmark fix is not a production fix. Three practices kept the gains in production.</p>

<p><strong>Continuous profiling.</strong> Capture periodic per-rank <code class="language-plaintext highlighter-rouge">nsys</code> timelines and NVTX-annotated
collective spans on a sample of the fleet, so a regression in all-to-all time is caught
as a <em>metric</em>, not a customer complaint.</p>

<p><strong>Fleet and topology management.</strong> The scheduler is topology-aware: jobs are placed in
<strong>rail-aligned placement groups</strong>, hot-expert replicas are spread across failure
domains, and nodes showing fabric degradation are <strong>drained</strong> rather than left to gate
collectives for everyone sharing their step.</p>

<p><strong>Production monitoring.</strong> The dashboards that mattered were not GPU utilization — they
were <em>network</em> signals:</p>

<ul>
  <li>per-step <strong>all-to-all duration</strong> (and its p99), the leading indicator;</li>
  <li><strong>per-expert load skew</strong>, to catch routing drift early;</li>
  <li>IB/RoCE <strong>congestion counters</strong> — PFC pause, ECN marks, switch-buffer occupancy;</li>
  <li><strong>NCCL collective time</strong> broken out from compute time via NVTX;</li>
  <li>DCGM fleet telemetry (<code class="language-plaintext highlighter-rouge">dcgmi dmon</code>) correlated with the above.</li>
</ul>

<p>The guiding principle: <strong>measure the network and the tail, because the mean will lie
to you.</strong></p>

<h2 id="15-key-takeaways">15. Key takeaways</h2>

<ol>
  <li><strong>MoE shifts the bottleneck from compute to communication.</strong> Saving FLOPs costs bytes.</li>
  <li><strong>Expert popularity creates network hotspots</strong> — hot experts plus synchronized incast.</li>
  <li><strong>GPU utilization hides network inefficiency.</strong> Healthy averages, idle tails.</li>
  <li><strong>Scaling GPUs alone may not raise throughput</strong> once you are past one node.</li>
  <li><strong>Future AI infrastructure must be communication-aware by design</strong> — topology,
placement, and collectives co-designed with the model.</li>
</ol>

<h2 id="16-open-questions">16. Open questions</h2>

<ul>
  <li>Can expert routing be made <strong>topology-aware</strong> at inference time without hurting quality?</li>
  <li>Can experts <strong>self-balance</strong> their load online as traffic drifts?</li>
  <li>Should expert <strong>placement be dynamic</strong>, migrating hot experts toward demand?</li>
  <li>What is the right <strong>benchmark for communication efficiency</strong> — a standardized
“all-to-all per token at the tail” metric the field could compare against?</li>
</ul>

<h2 id="references">References</h2>

<ol>
  <li>N. Shazeer et al., <em>Outrageously Large Neural Networks: The Sparsely-Gated
Mixture-of-Experts Layer</em>, ICLR 2017 (arXiv:1701.06538).</li>
  <li>D. Lepikhin et al., <em>GShard: Scaling Giant Models with Conditional Computation and
Automatic Sharding</em>, 2020 (arXiv:2006.16668).</li>
  <li>W. Fedus, B. Zoph, N. Shazeer, <em>Switch Transformers: Scaling to Trillion Parameter
Models with Simple and Efficient Sparsity</em>, JMLR 2022 (arXiv:2101.03961).</li>
  <li>S. Rajbhandari et al., <em>DeepSpeed-MoE: Advancing Mixture-of-Experts Inference and
Training to Power Next-Generation AI Scale</em>, ICML 2022 (arXiv:2201.05596).</li>
  <li>C. Hwang et al., <em>Tutel: Adaptive Mixture-of-Experts at Scale</em>, 2022 (arXiv:2206.03382).</li>
  <li>NVIDIA, <em>NCCL (NVIDIA Collective Communications Library) Documentation</em> — collectives,
transports, and environment variables.</li>
  <li>NVIDIA, <em>NVSHMEM Documentation</em> — GPU-initiated one-sided communication.</li>
  <li>NVIDIA, <em>Magnum IO and GPUDirect RDMA</em> technical documentation.</li>
  <li>NVIDIA, <em>NVLink and NVSwitch</em> (H100 / Hopper architecture whitepaper).</li>
  <li>NVIDIA, <em>Quantum-2 InfiniBand Platform and SHARP In-Network Computing</em> documentation.</li>
  <li>NVIDIA, <em>DGX SuperPOD Reference Architecture</em> — rail-optimized network design.</li>
  <li>NVIDIA, <em>Data Center GPU Manager (DCGM)</em> documentation — fleet telemetry.</li>
</ol>

<hr />

<p><em>This is part of an ongoing architecture-study series. Corrections and counterpoints
are welcome — the goal is to reason in public about how large AI systems actually behave
under load.</em></p>]]></content><author><name>Xariv Infrastructure</name></author><category term="AI Infrastructure" /><category term="MoE" /><category term="inference" /><category term="NVIDIA" /><category term="NCCL" /><category term="InfiniBand" /><category term="NVLink" /><category term="networking" /><category term="GPU" /><category term="distributed-systems" /><summary type="html"><![CDATA[An architecture case study on why scaling GPUs stopped improving throughput in a hypothetical 235B-parameter MoE answer-generation platform — and how networking, not compute, became the limiting factor on NVIDIA H100 fleets.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://manojkumar-github.github.io/assets/img/moe-architecture.svg" /><media:content medium="image" url="https://manojkumar-github.github.io/assets/img/moe-architecture.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Designing an Idempotent Webhook Pipeline</title><link href="https://manojkumar-github.github.io/idempotent-webhooks/" rel="alternate" type="text/html" title="Designing an Idempotent Webhook Pipeline" /><published>2026-06-12T00:00:00-05:00</published><updated>2026-06-12T00:00:00-05:00</updated><id>https://manojkumar-github.github.io/idempotent-webhooks</id><content type="html" xml:base="https://manojkumar-github.github.io/idempotent-webhooks/"><![CDATA[<p>Every webhook provider retries on failure, which means your handler <em>will</em> see the
same event twice. If processing isn’t idempotent, you get double charges, duplicate
emails, and corrupted state. Here’s the pipeline we settled on.</p>

<h2 id="the-core-idea">The core idea</h2>

<p>Treat the provider’s event ID as a unique key and record it the moment you start
processing. If you’ve seen it before, acknowledge and stop.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">processed_events</span> <span class="p">(</span><span class="n">event_id</span><span class="p">,</span> <span class="n">received_at</span><span class="p">)</span>
<span class="k">VALUES</span> <span class="p">(</span><span class="err">$</span><span class="mi">1</span><span class="p">,</span> <span class="n">now</span><span class="p">())</span>
<span class="k">ON</span> <span class="n">CONFLICT</span> <span class="p">(</span><span class="n">event_id</span><span class="p">)</span> <span class="k">DO</span> <span class="k">NOTHING</span>
<span class="n">RETURNING</span> <span class="n">event_id</span><span class="p">;</span>
</code></pre></div></div>

<p>If the <code class="language-plaintext highlighter-rouge">RETURNING</code> row is empty, it’s a duplicate — return <code class="language-plaintext highlighter-rouge">200</code> immediately so the
provider stops retrying.</p>

<h2 id="the-three-stages">The three stages</h2>

<ol>
  <li><strong>Verify</strong> the signature before trusting anything in the payload.</li>
  <li><strong>Deduplicate</strong> using the insert above, inside the same transaction as your work.</li>
  <li><strong>Process</strong> the side effect, then commit atomically.</li>
</ol>

<p>The crucial detail is step 2 and 3 sharing <strong>one transaction</strong>. If processing fails,
the dedup row rolls back too, so a legitimate retry can succeed.</p>

<h2 id="why-not-just-check-then-insert">Why not just check-then-insert?</h2>

<p>Because two concurrent deliveries can both pass the check before either inserts. The
<code class="language-plaintext highlighter-rouge">ON CONFLICT</code> approach pushes uniqueness into the database, where it’s actually safe
under concurrency.</p>

<p>This pattern has handled millions of events for us without a single duplicate-side-effect
incident since we shipped it.</p>]]></content><author><name>Marcus Lee</name></author><category term="Architecture" /><summary type="html"><![CDATA[Every webhook provider retries on failure, which means your handler will see the same event twice. If processing isn’t idempotent, you get double charges, duplicate emails, and corrupted state. Here’s the pipeline we settled on.]]></summary></entry><entry><title type="html">Cutting P99 Latency by 60% on Our Search Service</title><link href="https://manojkumar-github.github.io/cutting-p99-latency/" rel="alternate" type="text/html" title="Cutting P99 Latency by 60% on Our Search Service" /><published>2026-06-10T00:00:00-05:00</published><updated>2026-06-10T00:00:00-05:00</updated><id>https://manojkumar-github.github.io/cutting-p99-latency</id><content type="html" xml:base="https://manojkumar-github.github.io/cutting-p99-latency/"><![CDATA[<p>When our search API started missing its latency SLO, the averages looked fine — it
was the tail that hurt. This is a walkthrough of how we found the cause and the
change that brought P99 down from 820 ms to 320 ms.</p>

<h2 id="the-symptom">The symptom</h2>

<p>Dashboards showed a healthy median (~45 ms) but a P99 that spiked unpredictably to
nearly a second. Tail latency like this almost never comes from CPU; it comes from
<em>waiting</em> — locks, queues, or pools.</p>

<h2 id="finding-the-bottleneck">Finding the bottleneck</h2>

<p>We added per-request spans around three stages: auth, query planning, and the
database call. The data was unambiguous:</p>

<table>
  <thead>
    <tr>
      <th>Stage</th>
      <th>Median</th>
      <th>P99</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Auth</td>
      <td>2 ms</td>
      <td>4 ms</td>
    </tr>
    <tr>
      <td>Query planning</td>
      <td>8 ms</td>
      <td>11 ms</td>
    </tr>
    <tr>
      <td>Database call</td>
      <td>30 ms</td>
      <td><strong>790 ms</strong></td>
    </tr>
  </tbody>
</table>

<p>The database itself was fast. Requests were spending most of their time <em>waiting to
acquire a connection</em> from a pool that was sized for average load, not peak.</p>

<h2 id="the-fix">The fix</h2>

<p>Three changes, in order of impact:</p>

<ol>
  <li><strong>Right-sized the pool</strong> based on <code class="language-plaintext highlighter-rouge">peak_concurrency × avg_hold_time</code>, not a guessed number.</li>
  <li><strong>Added a short acquire timeout</strong> so a saturated pool fails fast instead of queueing.</li>
  <li><strong>Made slow queries observable</strong> with a log line above 100 ms.</li>
</ol>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pool</span> <span class="o">=</span> <span class="n">ConnectionPool</span><span class="p">(</span>
    <span class="n">min_size</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
    <span class="n">max_size</span><span class="o">=</span><span class="mi">64</span><span class="p">,</span>          <span class="c1"># was 20
</span>    <span class="n">timeout</span><span class="o">=</span><span class="mf">0.25</span><span class="p">,</span>         <span class="c1"># fail fast instead of queueing
</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="results">Results</h2>

<blockquote>
  <p>P99 dropped from 820 ms to 320 ms within an hour of deploy — and stayed flat
through the next traffic peak.</p>
</blockquote>

<p>No new servers, no query rewrites. The lesson we keep relearning: <strong>tail latency is
usually a queueing problem, not a compute problem.</strong></p>]]></content><author><name>Priya Nair</name></author><category term="Performance" /><summary type="html"><![CDATA[When our search API started missing its latency SLO, the averages looked fine — it was the tail that hurt. This is a walkthrough of how we found the cause and the change that brought P99 down from 820 ms to 320 ms.]]></summary></entry></feed>