<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashutosh Mishra</title>
    <description>The latest articles on DEV Community by Ashutosh Mishra (@ashutosh_mishra).</description>
    <link>https://dev.to/ashutosh_mishra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4110303%2F49cadb94-7aac-48af-9a3e-42981d1fe18c.png</url>
      <title>DEV Community: Ashutosh Mishra</title>
      <link>https://dev.to/ashutosh_mishra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashutosh_mishra"/>
    <language>en</language>
    <item>
      <title>BlitzBroker by Team CodeBlitz. A from-scratch MQTT Broker in Rust.</title>
      <dc:creator>Ashutosh Mishra</dc:creator>
      <pubDate>Tue, 08 Sep 2026 18:33:07 +0000</pubDate>
      <link>https://dev.to/ashutosh_mishra/blitzbroker-by-team-codeblitz-a-from-scratch-mqtt-broker-in-rust-2cff</link>
      <guid>https://dev.to/ashutosh_mishra/blitzbroker-by-team-codeblitz-a-from-scratch-mqtt-broker-in-rust-2cff</guid>
      <description>&lt;h2&gt;
  
  
  118 Green Tests. One Client Still Hanging.
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mosquitto_pub -q 1&lt;/code&gt; doesn't print much when it works. Connect, publish, get an ack, exit. Half a second, if that.&lt;/p&gt;

&lt;p&gt;Ours took four seconds. Then it timed out.&lt;/p&gt;

&lt;p&gt;Nothing had crashed. Nothing had printed an error. Our broker was up, accepting connections, parsing every byte correctly. 62 tests passing at that exact commit, every one of them green. A real MQTT client just sat there, waiting for an acknowledgment that was never going to come, because we had built half of a feature and tested only the half we'd built.&lt;/p&gt;

&lt;p&gt;That gap between "the tests pass" and "the thing works" turned out to be the actual subject of this project, more than the protocol was.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we were avoiding
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zerodepshack.com/" rel="noopener noreferrer"&gt;Zero Dependency&lt;/a&gt;'s rule is simple to state and expensive to keep: an empty manifest. No crates. We picked Track C, that is, Web &amp;amp; Network, and built &lt;a href="https://github.com/Dev-Am12/BlitzBroker" rel="noopener noreferrer"&gt;&lt;strong&gt;BlitzBroker&lt;/strong&gt;&lt;/a&gt;, an MQTT 3.1.1-subset pub/sub broker in Rust, &lt;code&gt;std&lt;/code&gt; only.&lt;/p&gt;

&lt;p&gt;MQTT, if you haven't touched it: clients connect to a broker, subscribe to named topics, publish messages, and the broker fans each message out to every current subscriber of that topic. It's the protocol under most "smart home" and IoT stacks: lightweight, binary, built for flaky connections. Normally you get it by running Mosquitto or EMQX, or by pulling in a client library and pointing it at someone else's broker. We wrote the broker.&lt;/p&gt;

&lt;p&gt;The honest reason to pick Rust for this specific event, rather than for its own sake: &lt;a href="https://doc.rust-lang.org/std/" rel="noopener noreferrer"&gt;Rust's &lt;code&gt;std&lt;/code&gt;&lt;/a&gt; gives you almost nothing for the "Web &amp;amp; Network" track. No async runtime. No HTTP. No JSON. No MQTT, obviously. Real Rust network code leans on &lt;code&gt;tokio&lt;/code&gt; and &lt;code&gt;serde&lt;/code&gt; almost by reflex, avoiding them here isn't a small flex, it's undoing the thing most Rust web code assumes on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the thing
&lt;/h2&gt;

&lt;p&gt;One broker thread, later four, each owning a disjoint slice of the topic registry, talking to connection threads only through channels. No shared-state locking on the registry, a topic either belongs to a thread or it doesn't, so there's nothing to race. &lt;code&gt;Register&lt;/code&gt; and &lt;code&gt;Disconnect&lt;/code&gt; broadcast to every shard, since a single client might end up with subscriptions scattered across more than one; everything else routes to exactly one shard, chosen by hashing the topic.&lt;/p&gt;

&lt;p&gt;That routing decision is also where the more interesting bug lived, but first: the queue.&lt;/p&gt;

&lt;p&gt;Every subscriber gets a bounded outbound queue. When it fills, a slow client, a burst of traffic, something has to give. &lt;code&gt;std::sync::mpsc::sync_channel(N)&lt;/code&gt; looked like the obvious tool here, until we actually read what it does under pressure: it blocks the &lt;em&gt;sender&lt;/em&gt; once full. That's exactly backwards for a broker. A stalled subscriber blocking the thread that's trying to serve every &lt;em&gt;other&lt;/em&gt; subscriber isn't backpressure, it's a single client taking the whole broker hostage. We wanted drop-oldest — discard the stalest buffered message, keep moving and &lt;code&gt;std&lt;/code&gt; doesn't hand you that. So it's a &lt;code&gt;Mutex&amp;lt;VecDeque&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; and a &lt;code&gt;Condvar&lt;/code&gt;, maybe forty lines, and it's the one piece of this project I'd point to as "yes, this is genuinely what the stdlib made painful": not that the primitives were missing, but that the one primitive that &lt;em&gt;was&lt;/em&gt; there had the wrong policy baked in, and there was no way to ask it for a different one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that actually ate an afternoon
&lt;/h2&gt;

&lt;p&gt;Wildcard subscriptions in MQTT let a client ask for &lt;code&gt;sensors/+/temp&lt;/code&gt; and receive publishes to &lt;code&gt;sensors/kitchen/temp&lt;/code&gt;, &lt;code&gt;sensors/garage/temp&lt;/code&gt;, anything matching that shape. We wrote the matcher iterative, deliberately not recursive, since both the topic and the filter are attacker-controlled strings arriving off the wire and a recursive matcher is a stack-exhaustion attack waiting to happen, tested it thoroughly against the spec's own worked examples, wired it into the broker's publish path. Subscribed with a wildcard, published to a matching topic, watched it arrive. Shipped it.&lt;/p&gt;

&lt;p&gt;Then we added sharding, and it broke, the same way the QoS1 gap did. No error, no panic, just a wildcard subscriber that stopped receiving anything.&lt;/p&gt;

&lt;p&gt;The routing rule hashes the topic &lt;em&gt;string&lt;/em&gt; to pick a shard. That's correct for exact matches: a subscription to &lt;code&gt;"sensors/temp"&lt;/code&gt; and a publish to &lt;code&gt;"sensors/temp"&lt;/code&gt; are the same string, same hash, same shard, every time. It's wrong for wildcards, and it took an embarrassingly long time to see why: &lt;code&gt;"sensors/+/temp"&lt;/code&gt; and &lt;code&gt;"sensors/kitchen/temp"&lt;/code&gt; are &lt;em&gt;different strings&lt;/em&gt;. They hash to different shards, almost certainly. The subscription succeeds. The shard holding it just never sees the publish that should have matched it, because that publish landed on a different shard entirely, one that has no idea the wildcard filter exists.&lt;/p&gt;

&lt;p&gt;The fix, once we saw it clearly, was one sentence: treat a wildcard subscription like &lt;code&gt;Register&lt;/code&gt; or &lt;code&gt;Disconnect&lt;/code&gt;, broadcast it to every shard, not just one. Exact-match subscriptions keep routing by hash; wildcard ones go everywhere, so whichever shard eventually gets the matching publish already has the filter to check it against. We verified it the only way that felt honest after the first miss: real &lt;code&gt;mosquitto_pub&lt;/code&gt;/&lt;code&gt;mosquitto_sub&lt;/code&gt;, eight different retained topics deliberately spread across shards, one wildcard subscriber, all eight arriving. Not because a unit test said so, because we watched it happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  The half-built feature
&lt;/h2&gt;

&lt;p&gt;Which brings back the four-second hang. MQTT's QoS 1 means "the broker must acknowledge receipt of this publish." We built the wire format for that acknowledgment: encode it, decode it, round-trip it and wrote tests proving the bytes were exactly right. What we hadn't built was the broker actually &lt;em&gt;sending&lt;/em&gt; one when a client published at QoS 1. Every test we'd written was protocol-layer: bytes in, struct out, struct in, bytes out. None of them ever ran the connection-handling code that's supposed to notice "this was QoS 1, better say something back" because that logic didn't exist yet, and a test can't fail to cover code that isn't there.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mosquitto_pub -q 1&lt;/code&gt; was the first thing that ever actually waited for that acknowledgment instead of just checking whether the bytes we produced were well-formed. It hung, because we'd never asked anything to wait before.&lt;/p&gt;

&lt;p&gt;Same lesson, twice, in one project: encode/decode tests prove your wire format is correct in isolation. They prove nothing about whether the broker &lt;em&gt;behaves&lt;/em&gt; correctly end to end. The only way we found either gap was pointing a real, independent MQTT client at the compiled binary and watching what it actually did not what our own code claimed or the AI agent claimed it would do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bonus we didn't take
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zerodepshack.com/" rel="noopener noreferrer"&gt;Zero Dependency&lt;/a&gt; offers a "Single File" bonus, that is, the whole submission as one source file someone could read top to bottom. We tried. A branch exists, ~3,885 lines, compiles, passes the full test suite.&lt;/p&gt;

&lt;p&gt;It's not a single-file program. It's a single &lt;em&gt;file&lt;/em&gt;. Every &lt;code&gt;mod&lt;/code&gt; boundary from the multi-file layout got preserved wholesale, the module walls are all still there, just copy-pasted into one document instead of split across several. That's a stapled concatenation, not the thing the bonus is actually asking for, and we knew the difference the moment we looked at it honestly.&lt;/p&gt;

&lt;p&gt;We didn't claim it. It's disclosed in the README as attempted and not achieved, the branch stayed public, and the bonus tally doesn't include it. It would have been trivial to point at "one file, compiles, tests pass" and call it done and nobody skimming a submission list would have caught the difference on the first pass. But this whole event is built around the idea that a naive, honestly-disclosed gap is worth more than a confident claim that doesn't survive a second look, and once you've internalized that watching your own QoS1 hang, it's hard to selectively unlearn it for the bonus you'd rather have.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually got killed
&lt;/h2&gt;

&lt;p&gt;No &lt;a href="https://github.com/tokio-rs/tokio" rel="noopener noreferrer"&gt;&lt;code&gt;tokio&lt;/code&gt;&lt;/a&gt;, thread-per-connection plus a channel-based actor model instead of an async runtime. No &lt;a href="https://github.com/serde-rs/serde" rel="noopener noreferrer"&gt;&lt;code&gt;serde&lt;/code&gt;&lt;/a&gt;, the entire MQTT codec, every packet type, hand-rolled against the spec. No &lt;a href="https://github.com/crossbeam-rs/crossbeam" rel="noopener noreferrer"&gt;&lt;code&gt;crossbeam&lt;/code&gt;&lt;/a&gt;, the drop-oldest bounded queue above, built because the stdlib's one bounded-channel primitive had a backpressure policy we didn't want, not because a policy was missing entirely. No &lt;code&gt;mqtt&lt;/code&gt;/&lt;code&gt;aedes&lt;/code&gt;, the packages you'd actually reach for to do exactly this locally, without thinking about it, in about four lines and one &lt;code&gt;npm install&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision I'd take back
&lt;/h2&gt;

&lt;p&gt;Small, and it cost real time rather than teaching us anything: our decision log kept colliding. More than once, someone edited it from a copy that predated the last person's changes, and a decision we'd already written down quietly vanished, replaced by someone else's entry claiming the same slot. Not a code bug but rather a coordination one, which is anyways understandable for a team of 4. The fix was never clever, just "pull the actual current version of a shared file before you touch it," and we should have said that out loud on day one instead of relearning it three separate times.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers, honestly
&lt;/h2&gt;

&lt;p&gt;118 automated tests, all passing, none of them the reason we found either real gap, live testing against actual clients was. A four-shard broker pushing roughly 495k msg/s against a single-shard broker's 402k at high concurrency across 64 topics. A real improvement, and a modest one, because at this scale the network syscalls dominate over how many threads are splitting the registry, and we'd rather say that plainly than let a comparison table imply more than it earned. Thirteen documented stdlib substitutions. Zero entries in &lt;code&gt;cargo tree&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The bug that mattered most wasn't in the MQTT spec, and it wasn't really in our code either. It was in trusting a test suite to tell us something it was never actually testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;Win or not, this was again one of the most fun 72 hours I've spent building something on a Hackathon Raptor's Hackthon. I cannot thank enough to my teammates at Team CodeBlitz for the experience and knowledge we shared together. We're eagerly waiting for results and feedback from the esteemed judges.&lt;/p&gt;




&lt;p&gt;Repo: &lt;a href="https://github.com/Dev-Am12/BlitzBroker" rel="noopener noreferrer"&gt;https://github.com/Dev-Am12/BlitzBroker&lt;/a&gt;&lt;br&gt;
Demo: &lt;a href="https://drive.google.com/drive/folders/1ScvHPNuxs_JTPaasKMEvzKrL9Wo5OLah?usp=sharing" rel="noopener noreferrer"&gt;https://drive.google.com/drive/folders/1ScvHPNuxs_JTPaasKMEvzKrL9Wo5OLah?usp=sharing&lt;/a&gt;&lt;br&gt;
Built for &lt;strong&gt;Zero Dependency 2026&lt;/strong&gt;, run by &lt;a href="https://www.raptors.dev/" rel="noopener noreferrer"&gt;Hackathon Raptors&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hackathonraptors</category>
      <category>zerodependency</category>
      <category>rust</category>
      <category>network</category>
    </item>
  </channel>
</rss>
