<?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: Harihar Nautiyal</title>
    <description>The latest articles on Forem by Harihar Nautiyal (@hariharnautiyal).</description>
    <link>https://forem.com/hariharnautiyal</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%2F3653911%2F58e782fe-abd6-4ede-b293-4f5c8c2184fe.png</url>
      <title>Forem: Harihar Nautiyal</title>
      <link>https://forem.com/hariharnautiyal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hariharnautiyal"/>
    <language>en</language>
    <item>
      <title>Stop Using Raw UUIDs: Type-Safe, Prefixed IDs in Rust (Stripe-style)</title>
      <dc:creator>Harihar Nautiyal</dc:creator>
      <pubDate>Wed, 24 Dec 2025 05:46:37 +0000</pubDate>
      <link>https://forem.com/hariharnautiyal/stop-using-raw-uuids-type-safe-prefixed-ids-in-rust-stripe-style-2a6h</link>
      <guid>https://forem.com/hariharnautiyal/stop-using-raw-uuids-type-safe-prefixed-ids-in-rust-stripe-style-2a6h</guid>
      <description>&lt;p&gt;We have all been there. You are staring at your server logs at 2 AM, trying to debug a request, and you see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processing request for ID: 550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is that a &lt;strong&gt;User ID&lt;/strong&gt;? An &lt;strong&gt;Order ID&lt;/strong&gt;? An &lt;strong&gt;API Key&lt;/strong&gt;? Who knows. It’s just a blob of hex characters.&lt;/p&gt;

&lt;p&gt;Even worse, have you ever written a function like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Uuid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you accidentally call &lt;code&gt;process_payment(order_id, user_id)&lt;/code&gt;, the compiler won’t stop you. They are both just &lt;code&gt;Uuid&lt;/code&gt;. You won't find out until your database throws a "Record not found" error—or worse, you corrupt data.&lt;/p&gt;

&lt;p&gt;I’ve always admired how &lt;strong&gt;Stripe&lt;/strong&gt; handles this. Their IDs look like &lt;code&gt;cus_018...&lt;/code&gt; or &lt;code&gt;ch_018...&lt;/code&gt;. They are self-describing and readable.&lt;/p&gt;

&lt;p&gt;I wanted that same experience in Rust, but with the compiler enforcing safety. So, I built &lt;strong&gt;&lt;a href="https://github.com/h01-team/puuid" rel="noopener noreferrer"&gt;puuid&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is puuid?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;puuid&lt;/code&gt; (Prefixed UUID) is a lightweight Rust crate that wraps the standard &lt;code&gt;uuid&lt;/code&gt; library. It gives you two main things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Readability:&lt;/strong&gt; IDs print as &lt;code&gt;"user_018c..."&lt;/code&gt; instead of just numbers.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Type Safety:&lt;/strong&gt; You cannot mix up a &lt;code&gt;UserId&lt;/code&gt; with an &lt;code&gt;OrderId&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;It’s surprisingly simple to set up. You define your prefixes once (usually in your &lt;code&gt;types.rs&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;puuid&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Puuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Define your prefixes&lt;/span&gt;
&lt;span class="nd"&gt;prefix!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;prefix!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ord"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Create strong types&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Puuid&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;OrderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Puuid&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, look at what happens when we try to make that mistake from earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;delete_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Deleting order: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_v7&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// ❌ COMPILE ERROR: expected OrderId, found UserId&lt;/span&gt;
    &lt;span class="nf"&gt;delete_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rust compiler now protects you from your own typos.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But does it kill performance?"
&lt;/h2&gt;

&lt;p&gt;This was my main concern when building it. The answer is &lt;strong&gt;no&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Puuid&amp;lt;T&amp;gt;&lt;/code&gt; is a &lt;code&gt;#[repr(transparent)]&lt;/code&gt; wrapper around the standard &lt;code&gt;uuid::Uuid&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Memory:&lt;/strong&gt; It takes up the exact same space as a standard UUID (16 bytes).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Database:&lt;/strong&gt; You can insert it directly as a UUID type (via &lt;code&gt;.into_inner()&lt;/code&gt;) or store it as text if you want to keep the prefix visible.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Methods:&lt;/strong&gt; It implements &lt;code&gt;Deref&lt;/code&gt;, so you can still call &lt;code&gt;.as_bytes()&lt;/code&gt;, &lt;code&gt;.get_version()&lt;/code&gt;, or any other method from the standard &lt;code&gt;uuid&lt;/code&gt; crate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Note on UUID v7
&lt;/h2&gt;

&lt;p&gt;By default, &lt;code&gt;puuid&lt;/code&gt; encourages &lt;strong&gt;UUID v7&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you haven't switched from v4 (random) to v7 yet, you should. v7 UUIDs are &lt;strong&gt;time-sortable&lt;/strong&gt;. This means that when you store them in a database, they naturally index according to time creation. It prevents index fragmentation and makes &lt;code&gt;INSERT&lt;/code&gt; performance much faster for large tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_v7&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Output: user_018c6427-4f30-7f89-a1b2-c3d4e5f67890&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Serde is Magic
&lt;/h2&gt;

&lt;p&gt;If you are building a JSON API (with Axum, Actix, etc.), &lt;code&gt;puuid&lt;/code&gt; handles the serialization for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Serialize,&lt;/span&gt; &lt;span class="nd"&gt;Deserialize)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Checkout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a client sends this JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ord_018..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user_018..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works perfectly. But if they send a raw UUID or mix up the prefixes, the deserializer rejects it immediately with a validation error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;I’d love to hear your thoughts on the API design. I’ve been using it in my own projects to clean up my logs and it has saved me from at least three "argument swap" bugs already.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crates.io:&lt;/strong&gt; &lt;a href="https://crates.io/crates/puuid" rel="noopener noreferrer"&gt;crates.io/crates/puuid&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://h01.in/projects/puuid" rel="noopener noreferrer"&gt;h01.in/projects/puuid&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/h01-team/puuid" rel="noopener noreferrer"&gt;github.com/h01-team/puuid&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think! 🦀&lt;/p&gt;

</description>
      <category>rust</category>
      <category>backend</category>
      <category>webdev</category>
      <category>database</category>
    </item>
    <item>
      <title>Why I chose Rust over Node.js for my Code Execution Backend</title>
      <dc:creator>Harihar Nautiyal</dc:creator>
      <pubDate>Tue, 09 Dec 2025 14:53:23 +0000</pubDate>
      <link>https://forem.com/hariharnautiyal/why-i-chose-rust-over-nodejs-for-my-code-execution-backend-hff</link>
      <guid>https://forem.com/hariharnautiyal/why-i-chose-rust-over-nodejs-for-my-code-execution-backend-hff</guid>
      <description>&lt;p&gt;I’m building a coding platform (Unifwe) where users run untrusted code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4899bfnft3utlpk754m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4899bfnft3utlpk754m0.png" alt=" " width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Problem: Running user code is dangerous. You need sandboxing. Node.js is great, but heavy for spinning up thousands of isolated instances.&lt;/p&gt;

&lt;p&gt;Why Rust? :&lt;br&gt;
    Memory safety (critical for sandboxes).&lt;br&gt;
    Performance (cold start times were 40000 ms faster).&lt;br&gt;
    WebAssembly potential.&lt;/p&gt;

&lt;p&gt;The Architecture: Briefly explain how your Next.js frontend sends code to the Rust API.&lt;/p&gt;

&lt;p&gt;It was hard to build, but the speed is worth it.&lt;/p&gt;

&lt;p&gt;if you want to test the speed of the engine, you can try the challenges here: &lt;a href="https://unifwe.h01.in/courses/7400777905099243520" rel="noopener noreferrer"&gt;Demo course&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqld0dfarwkpl3onnvbpx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqld0dfarwkpl3onnvbpx.png" alt="Course demo" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
