<?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>Forem: Abdul-Salam Zakaria</title>
    <description>The latest articles on Forem by Abdul-Salam Zakaria (@abdulsalamzak).</description>
    <link>https://forem.com/abdulsalamzak</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3810757%2Fefb1d8b2-368c-4d1c-8465-d7e1d01676a1.png</url>
      <title>Forem: Abdul-Salam Zakaria</title>
      <link>https://forem.com/abdulsalamzak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/abdulsalamzak"/>
    <language>en</language>
    <item>
      <title>Week 6: How GusLift Matches Rides in Real Time</title>
      <dc:creator>Abdul-Salam Zakaria</dc:creator>
      <pubDate>Sun, 15 Mar 2026 13:41:03 +0000</pubDate>
      <link>https://forem.com/guslift/week-6-how-guslift-matches-rides-in-real-time-41pl</link>
      <guid>https://forem.com/guslift/week-6-how-guslift-matches-rides-in-real-time-41pl</guid>
      <description>&lt;p&gt;Every school morning, a few drivers leave their dorms for campus, and a bunch of riders need seats. The core problem: match them fast, in the right direction, before the window closes.&lt;/p&gt;

&lt;p&gt;Here's how the matching engine actually works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Matching Room Abstraction
&lt;/h2&gt;

&lt;p&gt;We don't run one global pool. We partition by location, day, and departure time. A room key looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Westie:mon:08:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That string becomes the identity of a Cloudflare Durable Object(DO), a live, in-memory process that owns all real-time state for that slot. Everyone heading from Westie at 8am Monday shares one room. Leaving at 10:30? Different room entirely. This keeps each instance small and focused. The matching room doesn't know or care about any other departure window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Into the Right Room
&lt;/h2&gt;

&lt;p&gt;When a user opens the app, a Cloudflare Worker handles the request. It authenticates, resolves the user's schedule, generates the slot key, and forwards the WebSocket connection to the right DO. The Worker is stateless, purely a router. All the interesting state lives in the object it points to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the DO Tracks
&lt;/h2&gt;

&lt;p&gt;Four things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;drivers&lt;/code&gt; — map of driver ID → seats remaining&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;riders_waiting&lt;/code&gt; — FIFO queue of riders requesting a ride&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pending_matches&lt;/code&gt; — riders a driver has selected but who haven't confirmed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;connections&lt;/code&gt; — live WebSocket handles, one per user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every state change broadcasts to all connected clients. The frontend is a mirror of what the DO holds, nothing more.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;Driver goes online → sends &lt;code&gt;driver_online&lt;/code&gt; with seat count → registered in the room, broadcast to everyone. Rider wants a seat → sends &lt;code&gt;rider_request&lt;/code&gt; → added to the queue.&lt;/p&gt;

&lt;p&gt;Driver picks someone. That rider moves out of &lt;code&gt;riders_waiting&lt;/code&gt; into &lt;code&gt;pending_matches&lt;/code&gt; and gets a &lt;code&gt;match_request&lt;/code&gt; pushed to their socket. They have 30 seconds to accept. No response → back to the queue. They accept → seat decrements, ride written to Postgres, room updates for everyone.&lt;/p&gt;

&lt;p&gt;The part that could get hairy is concurrent events — two drivers selecting the same rider at the same time. The DO's single-threaded execution model handles that without any extra locking. One message at a time, in order. It's one of the legitimately nice properties of this architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Durable Objects
&lt;/h2&gt;

&lt;p&gt;Serverless and WebSockets are a bad pairing by default. Serverless assumes requests are stateless and short-lived; a WebSocket is neither. DOs give you a persistent, single-threaded process with in-memory state that survives across events. For a campus app where load is concentrated in a 20-minute morning window, you get rooms that spin up when needed and hibernate when not. No idle infrastructure, no connection hand-off problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Left
&lt;/h2&gt;

&lt;p&gt;A few open problems the current design doesn't address: drivers who cancel after a match is accepted, rooms that never get cleaned up after their departure window passes, and rate limiting on socket events. None of these tasks is difficult in principle. They just weren't the initial challenges.&lt;/p&gt;

</description>
      <category>cloudflare</category>
      <category>infrastructure</category>
      <category>backenddevelopment</category>
      <category>database</category>
    </item>
  </channel>
</rss>
