<?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: Venkat</title>
    <description>The latest articles on DEV Community by Venkat (@vrannang1).</description>
    <link>https://dev.to/vrannang1</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%2F1243027%2F015d4059-e23e-45cf-a1d1-dc3017b2d894.png</url>
      <title>DEV Community: Venkat</title>
      <link>https://dev.to/vrannang1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vrannang1"/>
    <language>en</language>
    <item>
      <title>Why Rust Feels Hard (And Why That's Actually the Point)</title>
      <dc:creator>Venkat</dc:creator>
      <pubDate>Sat, 09 May 2026 18:05:09 +0000</pubDate>
      <link>https://dev.to/vrannang1/why-rust-feels-hard-and-why-thats-actually-the-point-4ge5</link>
      <guid>https://dev.to/vrannang1/why-rust-feels-hard-and-why-thats-actually-the-point-4ge5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Part 1 of the "Rust Without the Headache" series&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let me tell you about the bug that broke me.&lt;/p&gt;

&lt;p&gt;I was working on a Python service—nothing crazy. Just a background worker that processed incoming data and wrote results to a database. It ran fine for months. Then one day in production, around 2 AM, it started corrupting data. Silently. No exception, no stack trace. Just wrong numbers in the database.&lt;/p&gt;

&lt;p&gt;It took me three days to find the problem. A dictionary was getting mutated by one part of the code while another part was reading from it. Completely valid Python. The interpreter was totally fine with it. My users were not.&lt;/p&gt;

&lt;p&gt;I'd seen similar things happen in .NET too—race conditions, null reference exceptions that only showed up under load, or async code that deadlocked because someone forgot a ConfigureAwait(false). The runtime would just shrug and carry on. Meanwhile, I'd be debugging for days.&lt;/p&gt;

&lt;p&gt;That's when I started looking at Rust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My First Impression (and probably yours too)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I opened the Rust book, got about two chapters in, and immediately felt like I was being lectured by a very strict professor who kept saying "no" without fully explaining why.&lt;/p&gt;

&lt;p&gt;"No, you can't use that variable anymore."&lt;br&gt;
"No, you can't mutate this here."&lt;br&gt;
"No, no, no."&lt;/p&gt;

&lt;p&gt;I remember thinking: Why is this so hard? Python and .NET don't make me jump through these hoops. Why can't Rust just trust me?&lt;/p&gt;

&lt;p&gt;So I closed the book and went back to what I knew. Classic move, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Second Attempt (that actually stuck)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few months later, a coworker showed me something that changed my perspective. He was building a small CLI tool in Rust—nothing fancy, just something that read a config file and made an HTTP request. What struck me wasn't the code. It was how calm he was about deploying it.&lt;/p&gt;

&lt;p&gt;"I just don't worry about it," he said. "If it compiles, it works."&lt;/p&gt;

&lt;p&gt;I thought he was exaggerating. He wasn't.&lt;/p&gt;

&lt;p&gt;That's when I realized something: &lt;strong&gt;The borrow checker wasn't being mean to me. It was being honest with me&lt;/strong&gt;. All those silent bugs I'd chased in Python and .NET—the ones that only showed up at 2 AM under weird conditions—Rust was forcing me to think about them up front.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Mindset Shift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what I started to understand:&lt;/p&gt;

&lt;p&gt;In Python, you write code and hope it works. You test it. You run it. You deploy it. And maybe weeks later, it blows up in a way your tests never caught. Then you debug. Then you fix. Then you pray.&lt;/p&gt;

&lt;p&gt;In .NET, it's better—the compiler catches more, and the type system helps. But you still get null references. You still get race conditions. You still get &lt;em&gt;ObjectDisposedException&lt;/em&gt; from async code that ran in the wrong order. The runtime is friendly, but friendly doesn't mean safe.&lt;/p&gt;

&lt;p&gt;In Rust, the compiler is like that strict professor who won't let you hand in an assignment until every single problem is fixed. It feels annoying in the moment. But here's the thing—once you pass, you pass. No late-night surprises. No silent corruption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What This Series Will Do For You&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Look, I'm not going to pretend I'm a Rust expert or that I never fight with the compiler anymore. I do. But I've learned to stop fighting against it and start working with it. And that's what this series is about.&lt;/p&gt;

&lt;p&gt;We're going to take the painful parts of Rust—borrowing, lifetimes, Result vs panic, Send and Sync—and I'm going to explain them the way I wish someone had explained them to me. No academic papers. No cryptic compiler error printouts without context. Just real examples from someone who came from Python and .NET and needed Rust to make sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the full roadmap for all 10 parts:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1: Why Rust Feels Hard (And Why That's Actually the Point)&lt;/strong&gt; — You are here. The bug, the frustration, and why sticking with it is worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Ownership — the valet key, the library book, and the pen&lt;/strong&gt; — I'll explain ownership and borrowing using three simple analogies. By the end, you'll know why Rust won't let you use something after it's been taken away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 3: Lifetimes — the rental agreement that saved my data&lt;/strong&gt; — This is the part everyone's scared of. But once you think of lifetimes like a rental agreement (you can't stay after the lease ends), it actually makes sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 4: Smart pointers — Box, Rc, and why the heap isn't scary&lt;/strong&gt; — Coming from .NET or Python, you've used the heap forever without thinking about it. I'll show you when you need Box, when to use Rc, and why reference counting isn't cheating.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Part 5: Fearless concurrency — Arc, Mutex, and the multi-lane highway *&lt;/em&gt;— Remember that dictionary bug that broke me? Rust makes that impossible to compile. We'll use highway analogies to understand threads, sharing, and locking without losing your mind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 6: Types and error handling — goodbye null, hello Option&lt;/strong&gt; — You'll never have to check for null again. I'll show you how Option and Result replace all that defensive garbage, and why ? is better than try-catch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 7: Traits and generics — polymorphism without inheritance&lt;/strong&gt; — If you've used interfaces in C# or duck typing in Python, traits will feel familiar. But different. I'll show you the "ah-ha" moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 8: Unsafe — the construction zone and when to enter it&lt;/strong&gt; — Yes, you can do raw pointer stuff. No, you probably shouldn't. But when you need to, here's how without setting your foot on fire.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 9: One real Axum app — every concept in context&lt;/strong&gt; — We'll build a small web server with Axum. You'll see ownership, lifetimes, error handling, and concurrency all working together in a real project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 10: Where to go from here — building real projects and staying out of tutorial hell&lt;/strong&gt; — Next steps. The best crates. How to keep learning without getting stuck. And permission to still be frustrated sometimes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where You'll Still Get Frustrated (Being Honest)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm not selling magic. Rust still has rough edges. Compile times can be slow. Some error messages are still cryptic (though way better than they used to be). And sometimes you'll write something that feels obviously correct and the compiler just says "nope."&lt;/p&gt;

&lt;p&gt;You'll get frustrated. You'll want to quit. You might go back to Python or C# for a weekend just to feel productive again.&lt;/p&gt;

&lt;p&gt;That's fine. I did too.&lt;/p&gt;

&lt;p&gt;But here's what I can promise: If you stick with it through this series, you'll start to feel something unexpected. Not mastery—that takes time. But trust. You'll start to trust that when your Rust code compiles, it's actually going to do what you meant. Not what you accidentally typed.&lt;/p&gt;

&lt;p&gt;And coming from languages like Python and .NET, where the runtime happily says "sure, let's try that" right before falling on its face... that feeling is worth the headache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Part 2, we're going to write some real Rust code. And yes, we'll make the borrow checker angry. On purpose. So you can see what it's actually trying to tell you.&lt;/p&gt;

&lt;p&gt;See you there.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>beginners</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Building a Zero-Knowledge Dating Platform for HIV-Positive Communities</title>
      <dc:creator>Venkat</dc:creator>
      <pubDate>Mon, 02 Mar 2026 19:31:02 +0000</pubDate>
      <link>https://dev.to/vrannang1/building-a-zero-knowledge-dating-platform-for-hiv-positive-communities-5f5k</link>
      <guid>https://dev.to/vrannang1/building-a-zero-knowledge-dating-platform-for-hiv-positive-communities-5f5k</guid>
      <description>&lt;p&gt;&lt;em&gt;Erlang, Vue, and client-side encryption — by design, not as an afterthought.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;A close friend of mine works as an AIDS counsellor.&lt;/p&gt;

&lt;p&gt;One day she told me something I couldn't shake:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My clients want companionship. They want marriage. They want normalcy.&lt;br&gt;
But they're terrified of being exposed."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;She'd seen it over and over. People who were HIV-positive, stable on treatment, undetectable — but isolated. Dating apps didn't feel safe. Disclosure was complicated. A screenshot could cost someone their job. A database breach could shatter a life.&lt;/p&gt;

&lt;p&gt;Then she asked me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can you build something for them? But it has to be &lt;em&gt;completely&lt;/em&gt; private."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not &lt;em&gt;"secure enough."&lt;/em&gt; Not &lt;em&gt;"we encrypt passwords."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Completely private.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where this started — and where &lt;a href="https://hivpositivematches.com" rel="noopener noreferrer"&gt;HIVPositiveMatches.com&lt;/a&gt; came from.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Traditional Dating Apps Are Dangerous for This Community
&lt;/h2&gt;

&lt;p&gt;Most dating platforms are built on a silent assumption: &lt;strong&gt;the server is a trusted party.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server stores your profile&lt;/li&gt;
&lt;li&gt;The server reads your profile&lt;/li&gt;
&lt;li&gt;The server decides who sees your profile&lt;/li&gt;
&lt;li&gt;The server can be breached, subpoenaed, or misused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most people, that's an acceptable tradeoff. For HIV-positive communities, it isn't. Disclosure can affect employment, housing, family relationships, and mental health. The fear isn't paranoia — it's grounded in real consequences that real people have faced.&lt;/p&gt;

&lt;p&gt;Privacy here isn't a feature. It's psychological safety.&lt;/p&gt;

&lt;p&gt;So I flipped the premise entirely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What if the server never sees plaintext user data at all?&lt;/strong&gt;&lt;br&gt;
Not at rest. Not in logs. Not in admin dashboards. Not even temporarily.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question led to a zero-knowledge architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Principle: The Server as a Blind Courier
&lt;/h2&gt;

&lt;p&gt;Instead of a traditional CRUD backend that owns your data, the server becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cryptographic relay&lt;/li&gt;
&lt;li&gt;A coordination layer&lt;/li&gt;
&lt;li&gt;A match facilitator&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not a data owner&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything meaningful happens on the client. The server passes sealed envelopes. It never opens them.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Erlang + Yaws&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Vue 3 + Naive UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Google OAuth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cryptography&lt;/td&gt;
&lt;td&gt;TweetNaCl (client-side)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key derivation&lt;/td&gt;
&lt;td&gt;Handle + PIN (deterministic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encryption&lt;/td&gt;
&lt;td&gt;Hybrid symmetric + asymmetric&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each choice was made with one question in mind: &lt;em&gt;does this require the server to see sensitive data?&lt;/em&gt; If yes, we found another way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Authentication vs. Identity
&lt;/h2&gt;

&lt;p&gt;Google OAuth handles login and identity verification — nothing more.&lt;/p&gt;

&lt;p&gt;Once authenticated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The email is &lt;strong&gt;encrypted client-side&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Only a hash of the encrypted email is stored for lookup&lt;/li&gt;
&lt;li&gt;The server sees: OAuth provider, user role, membership tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. No name. No email in plaintext. No profile data of any kind.&lt;/p&gt;

&lt;p&gt;If the database leaks tomorrow, the attacker gets a list of meaningless hashes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Profiles Are Encrypted Before They Leave the Browser
&lt;/h2&gt;

&lt;p&gt;When a user builds their profile, this is what happens in the browser:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A symmetric AES key is generated locally&lt;/li&gt;
&lt;li&gt;The entire profile is encrypted with that key&lt;/li&gt;
&lt;li&gt;Only the encrypted blob — and the wrapped key — are sent to the server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What the database actually stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypted profile vault&lt;/li&gt;
&lt;li&gt;Encrypted card preview&lt;/li&gt;
&lt;li&gt;Wrapped encryption keys&lt;/li&gt;
&lt;li&gt;Public keys&lt;/li&gt;
&lt;li&gt;Search-safe hashed fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server never holds readable health data, lifestyle information, or personal details. Not because we deleted it — because &lt;strong&gt;we never had it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: No Passwords — Deterministic Key Derivation
&lt;/h2&gt;

&lt;p&gt;Traditional passwords are a liability. Reset flows, storage, hashing — every step is a potential leak.&lt;/p&gt;

&lt;p&gt;Instead, users choose a &lt;strong&gt;handle&lt;/strong&gt; and a &lt;strong&gt;PIN&lt;/strong&gt;. These become salt inputs for key derivation, entirely in the browser. The PIN is never transmitted. Never stored. The server cannot brute-force vaults even under a court order.&lt;/p&gt;

&lt;p&gt;The result: a login flow that feels simple, backed by cryptographic guarantees that don't depend on us doing the right thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Public/Private Keys for Matching
&lt;/h2&gt;

&lt;p&gt;Each user generates a key pair in the browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Public key&lt;/strong&gt; → sent to the server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private key&lt;/strong&gt; → encrypted locally using the PIN, never leaves the device in plaintext&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When two users match, vault keys are exchanged through a controlled wrapping flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User A's vault key is wrapped with their public key&lt;/li&gt;
&lt;li&gt;The server re-wraps it with User B's public key&lt;/li&gt;
&lt;li&gt;User B's frontend unwraps it locally&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it like a courier passing a sealed envelope to a new recipient — resealing it without ever reading what's inside.&lt;/p&gt;

&lt;p&gt;At no point does the server retain readable profile data from either user.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Erlang for Reliability at Scale
&lt;/h2&gt;

&lt;p&gt;Erlang wasn't chosen for novelty. It was chosen because this system demands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Massive concurrency&lt;/strong&gt; — many users, many cryptographic operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fault tolerance&lt;/strong&gt; — processes fail safely and independently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictable performance&lt;/strong&gt; — no surprises under load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yaws serves dynamic HTML with embedded session markers that Vue hydrates on the frontend. The result is a modern UI backed by a backend that is minimal, resilient, and has been battle-tested for decades in telecoms.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: AI Matching Without Exposing Interests
&lt;/h2&gt;

&lt;p&gt;Compatibility can't be computed server-side if the server can't read profiles. So we moved it to the browser.&lt;/p&gt;

&lt;p&gt;Each client:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generates embeddings locally from profile content&lt;/li&gt;
&lt;li&gt;Normalizes and binarizes them&lt;/li&gt;
&lt;li&gt;Sends only non-reversible binary hashes to the server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The server compares hashes using Hamming distance. It never sees raw interests, lifestyle traits, or "about me" text. AI-powered matching — without the AI ever knowing who it's matching.&lt;/p&gt;

&lt;p&gt;The next article in this series goes deep on how that works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Threat Model: What Happens When Everything Goes Wrong?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;What the attacker gets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database leak&lt;/td&gt;
&lt;td&gt;Encrypted blobs. Unreadable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rogue admin&lt;/td&gt;
&lt;td&gt;Nothing. No plaintext to access.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server compromise&lt;/td&gt;
&lt;td&gt;No sensitive data to steal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network interception&lt;/td&gt;
&lt;td&gt;TLS + client-side encryption.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legal pressure / subpoena&lt;/td&gt;
&lt;td&gt;Server literally cannot decrypt anything.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This isn't security through obscurity. The server &lt;em&gt;cannot&lt;/em&gt; betray users — not because we promise it won't, but because it architecturally &lt;em&gt;cannot&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That distinction matters. Promises can be broken. Math can't.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Building This Taught Me
&lt;/h2&gt;

&lt;p&gt;Most systems are designed around: &lt;em&gt;"How do we store and use data?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This one is built around: &lt;em&gt;"How do we avoid ever possessing data?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That shift changes everything — UX, backend design, matching logic, error handling, recovery flows. It forces a kind of humility: assume the server is a liability, not a guardian. Design accordingly.&lt;/p&gt;

&lt;p&gt;It also changes what it means to be accountable. I cannot read my users' profiles. That's not a limitation — it's the point.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Coming Next
&lt;/h2&gt;

&lt;p&gt;This post is the foundation. The series continues with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 2:&lt;/strong&gt; Zero-knowledge filtering using 32-bit bitmasks &lt;em&gt;(next)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3:&lt;/strong&gt; AI embeddings + Hamming distance matching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4:&lt;/strong&gt; Key-wrapping flows in practice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 5:&lt;/strong&gt; Account recovery without exposing secrets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 6:&lt;/strong&gt; UX patterns for client-side encryption&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This project started because a counsellor wanted her clients to feel safe finding love.&lt;/p&gt;

&lt;p&gt;It became one of the most technically challenging — and meaningful — systems I've ever built.&lt;/p&gt;

&lt;p&gt;For sensitive communities, privacy-first design isn't optional. &lt;strong&gt;It's the only ethical choice.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>cryptography</category>
      <category>erlang</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Rediscovering C++: Building a High-Performance Blog Engine in 2026</title>
      <dc:creator>Venkat</dc:creator>
      <pubDate>Wed, 25 Feb 2026 05:45:47 +0000</pubDate>
      <link>https://dev.to/vrannang1/rediscovering-c-building-a-high-performance-blog-engine-in-2026-3gf</link>
      <guid>https://dev.to/vrannang1/rediscovering-c-building-a-high-performance-blog-engine-in-2026-3gf</guid>
      <description>&lt;p&gt;I've been a programmer for… well, a long time. My early days were spent in the computer lab, practicing C and C++ on floppy disks — yes, actual floppy disks. After finishing my engineering degree, I drifted into Oracle ERP and database-heavy business applications. The problem? I loved coding, but my day-to-day was mostly SQL scripts and reports. Hands-on software engineering felt like a distant memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journey Back to Programming
&lt;/h2&gt;

&lt;p&gt;Fast forward to the pandemic era: remote work opened new doors. I finally had time to dive back into programming. I explored Erlang and Elixir, played around with eex, leex, and heex, and even worked on a small Elixir project. But frameworks were moving fast — LiveView, EEx → LEEx changes, constant churn.&lt;/p&gt;

&lt;p&gt;I experimented with a few other stacks. I tried the static HTML + dynamic marker approach in Rust (Actix) — caching the shell and letting the frontend hydrate the SPA worked beautifully. I also experimented with Erlang’s Yaws, using persistent_term for caching, which was actually where the idea first clicked for me.&lt;/p&gt;

&lt;p&gt;That’s when I thought: “Huh… if this can be done there, why not in C++?” Go Fiber was fun for prototypes, and Rust (Axum, Actix) was powerful, but I wanted to explore modern C++. One weekend, I stumbled upon an article about C++’s new features — smart pointers, co_await, coroutines — and it hit me. C++ had evolved tremendously in the past 20+ years. Could I build something high-performance, scalable, and modern in C++?&lt;/p&gt;

&lt;p&gt;The answer was yes, and that’s how my journey with &lt;strong&gt;Drogon C++&lt;/strong&gt; and &lt;strong&gt;Vue Naive UI&lt;/strong&gt; began.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;The architecture grew from a simple idea: serve a fast, server-rendered HTML shell, then hand off interactivity to the SPA. Here's how it works in practice:&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Caching System
&lt;/h3&gt;

&lt;p&gt;I built a &lt;code&gt;TemplateCache&lt;/code&gt; singleton in C++ that loads the static HTML shell once, splits it at a dynamic marker (&lt;code&gt;&amp;lt;!--APP_MARKER--&amp;gt;&lt;/code&gt;), and caches it in memory. This makes per-request rendering nearly free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TemplateCache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;div id=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt; data-initial-route=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Components
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Server-side control&lt;/strong&gt; – The backend holds the routes, knows the state of the application, and serves the initial page. No CORS issues, no REST API boilerplate just to get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPA hydration&lt;/strong&gt; – The &lt;code&gt;&amp;lt;div id="app"&amp;gt;&lt;/code&gt; marker hands over the page to a frontend framework (Vue in my case, but it could be React, Svelte, or SolidJS). The frontend hydrates the page and takes over reactivity, giving a full SPA experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async-ready backend&lt;/strong&gt; – I designed the architecture so async DB queries can be added cleanly using C++20 coroutines (co_await). This makes it easy to fetch dynamic content without blocking threads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling &amp;amp; deployment&lt;/strong&gt; – Containers and Traefik handle load balancing. Multiple replicas of the same service can run, and because the static shell is cached, initial page rendering is consistent and fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt; – This setup decouples the backend and frontend enough that I can experiment with different frontend frameworks without touching the core C++ server. The backend just serves the shell + dynamic markers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Technical Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Backend: Modern C++ with Drogon&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drogon Framework&lt;/strong&gt;: High-performance HTTP application framework&lt;br&gt;
&lt;strong&gt;C++20 Features&lt;/strong&gt;: Coroutines, smart pointers, RAII&lt;br&gt;
&lt;strong&gt;Template System&lt;/strong&gt;: Custom caching layer for optimal performance&lt;br&gt;
&lt;strong&gt;Container Ready&lt;/strong&gt;: Docker + Traefik for production deployment&lt;br&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Vue.js Ecosystem&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: Reactive frontend framework&lt;br&gt;
&lt;strong&gt;Naive UI&lt;/strong&gt;: Clean, modern component library&lt;br&gt;
&lt;strong&gt;SPA Architecture&lt;/strong&gt;: Full client-side routing and state management&lt;br&gt;
&lt;strong&gt;Framework Agnostic&lt;/strong&gt;: Easy to swap for React, Svelte, or others&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementation Deep Dive
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Template Cache Pattern&lt;/strong&gt;&lt;br&gt;
The core innovation is the template caching system. Instead of rendering HTML on every request, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the base HTML template once at startup&lt;/li&gt;
&lt;li&gt;Split it at the app marker (&amp;lt;!--APP_MARKER--&amp;gt;)&lt;/li&gt;
&lt;li&gt;Cache both parts in memory&lt;/li&gt;
&lt;li&gt;Assemble responses by injecting dynamic content between cached parts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Near-zero template rendering overhead&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistent response times&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory-efficient caching&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy dynamic content injection&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Async Database Integration
&lt;/h3&gt;

&lt;p&gt;With C++20 coroutines, adding async database operations becomes elegant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Hypothetical async DB query
co_await auto posts = db.query("SELECT * FROM posts WHERE active = 1");
std::string dynamicContent = renderPosts(posts);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The coroutine support means we can handle thousands of concurrent requests without blocking threads on I/O operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Hydration Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The frontend receives a server-rendered shell with routing information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;html
&amp;lt;div id="app" data-initial-route="/blog/my-post"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue then hydrates this element and takes over:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const app = createApp(App);
const initialRoute = document.getElementById('app').dataset.initialRoute;
app.mount('#app');
router.push(initialRoute);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Approach Works
&lt;/h3&gt;

&lt;p&gt;I want to be clear: this isn't about saying other stacks are bad. Laravel, Django, Elixir, Go, Rust — all great choices.&lt;/p&gt;

&lt;p&gt;For me, it was about experimenting with C++ and seeing how far I could take it. With modern C++ features — smart pointers, RAII, co_await — building this architecture was surprisingly straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Benefits I Discovered&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Performance by Design&lt;/strong&gt; – Compiled C++ backend with memory-efficient caching delivers consistently fast responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt; – Modern C++ feels nothing like the C++ of the '90s. Smart pointers eliminate most memory management headaches, and coroutines make async code readable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment Simplicity&lt;/strong&gt; – Single binary deployment with no runtime dependencies makes containerization trivial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Freedom&lt;/strong&gt; – The backend serves a generic HTML shell, so I can experiment with any frontend framework without backend changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling Characteristics&lt;/strong&gt; – Multiple stateless instances behind a load balancer, with shared caching strategies when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Performance&lt;/strong&gt;&lt;br&gt;
In early testing, the template caching approach delivers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sub-millisecond template rendering&lt;/strong&gt; for cached shells&lt;br&gt;
&lt;strong&gt;Minimal memory footprint&lt;/strong&gt; compared to interpreted languages&lt;br&gt;
&lt;strong&gt;Excellent CPU utilization&lt;/strong&gt; under load&lt;br&gt;
&lt;strong&gt;Fast cold starts&lt;/strong&gt; in containerized environments&lt;/p&gt;

&lt;p&gt;The combination of compiled performance and modern async patterns creates a compelling foundation for high-traffic applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lessons Learned
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What Worked Really Well&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No CORS drama&lt;/strong&gt; – Because the server holds the routes and serves the initial page, I don't have to fight cross-origin requests for SPA hydration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server maintains control&lt;/strong&gt; – The backend is aware of the application state, initial routes, and template shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPA flexibility&lt;/strong&gt; – I can swap Vue for React, Svelte, or SolidJS without touching backend logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance matters&lt;/strong&gt; – Cached static shell + dynamic marker approach ensures a fast first load, while async DB queries (when added) can handle personalized content efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Surprising Discoveries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modern C++ is web-ready&lt;/strong&gt; – Smart pointers, thread safety, and coroutines make high-performance, maintainable backend code feasible without the pain of manual memory management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drogon is production-ready&lt;/strong&gt; – The framework handles HTTP/2, WebSockets, middleware, and all the modern web server features you'd expect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development velocity&lt;/strong&gt; – Once the architecture was in place, adding new routes and frontend components became surprisingly fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  Looking Forward
&lt;/h3&gt;

&lt;p&gt;This experiment has rekindled my appreciation for C++ in the modern web development landscape. While it's certainly not the right choice for every project, there are compelling use cases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High-performance APIs&lt;/strong&gt; that need to handle thousands of requests per second&lt;br&gt;
&lt;strong&gt;Real-time applications&lt;/strong&gt; where latency matters&lt;br&gt;
&lt;strong&gt;Resource-constrained environments&lt;/strong&gt; where memory and CPU efficiency are critical&lt;br&gt;
&lt;strong&gt;Long-running services&lt;/strong&gt; where the compile-time investment pays dividends&lt;/p&gt;

&lt;p&gt;The combination of C++20 features, mature frameworks like Drogon, and modern deployment practices makes C++ a viable option for web applications in 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  The finished product
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://thedeveloper.tech" rel="noopener noreferrer"&gt;https://thedeveloper.tech&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;If you're curious about modern C++ for web development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start with Drogon&lt;/strong&gt; – The documentation is excellent and the framework handles the HTTP complexities&lt;br&gt;
&lt;strong&gt;Experiment with coroutines&lt;/strong&gt; – C++20's co_await makes async code much more manageable&lt;br&gt;
&lt;strong&gt;Keep it simple&lt;/strong&gt; – Start with basic request/response patterns before adding complex features&lt;br&gt;
&lt;strong&gt;Leverage existing tools&lt;/strong&gt; – Docker, monitoring, and deployment practices work just as well with C++&lt;/p&gt;

&lt;p&gt;The web development landscape is vast, and there's room for many approaches. Sometimes, revisiting an old friend with fresh eyes can lead to surprisingly modern solutions.&lt;/p&gt;

&lt;p&gt;What's your experience with C++ in modern development? Have you tried any compiled languages for web backends recently? I'd love to hear about your experiments in the comments!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>learning</category>
      <category>performance</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
