<?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: Gilbert Silver</title>
    <description>The latest articles on DEV Community by Gilbert Silver (@thaarcadeguy).</description>
    <link>https://dev.to/thaarcadeguy</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%2F3982904%2F24ef225a-856d-4569-b83d-5016093b4572.jpg</url>
      <title>DEV Community: Gilbert Silver</title>
      <link>https://dev.to/thaarcadeguy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thaarcadeguy"/>
    <language>en</language>
    <item>
      <title>Late Nights and Fixes: Two Internship Tasks That Stuck</title>
      <dc:creator>Gilbert Silver</dc:creator>
      <pubDate>Sat, 13 Jun 2026 15:58:34 +0000</pubDate>
      <link>https://dev.to/thaarcadeguy/late-nights-and-fixes-two-internship-tasks-that-stuck-34lb</link>
      <guid>https://dev.to/thaarcadeguy/late-nights-and-fixes-two-internship-tasks-that-stuck-34lb</guid>
      <description>&lt;p&gt;The HNG Internship has been a wild ride. Between the tight deadlines, the late-night debugging sessions, and the sheer volume of new concepts thrown at me, there were moments I questioned my sanity. But looking back, the challenges that nearly broke me are exactly the ones I'm most grateful for. Here are two tasks that stuck with me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 1: The Append-Only Event Store (Individual Stage)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What it was&lt;/strong&gt;&lt;br&gt;
Build a key-value store from scratch. No PostgreSQL. No MongoDB. Just a file, an index, and the guarantee that data survives a crash.&lt;/p&gt;

&lt;p&gt;The spec was simple: accept events via HTTP, store them in an append-only log file, and read them back by ID. Oh, and when the server restarts? Rebuild everything from that file. No data loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem it was solving&lt;/strong&gt;&lt;br&gt;
Every database does this. PostgreSQL has its Write-Ahead Log. Redis has AOF. But I never understood why until I had to build it myself.&lt;/p&gt;

&lt;p&gt;The problem is crash recovery. If a server dies mid-write, how do you guarantee that old data isn't corrupted? The answer is append-only. You never edit. You only add. If power fails during a write, the worst case is losing that one line. Everything before it stays intact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I approached it&lt;/strong&gt;&lt;br&gt;
I started with the simplest thing that could work. Open a file, write a line, close it. Then I added the index a JavaScript Map that stores where each event lives in the file. Then I added the restart test. Stop the server. Start it again. Make sure the data is still there.&lt;/p&gt;

&lt;p&gt;The hardest part was resisting the urge to use SQLite. The spec said no databases. I had to understand file I/O at a level I never had before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What broke and how I fixed it&lt;/strong&gt;&lt;br&gt;
Unicode.&lt;/p&gt;

&lt;p&gt;I wrote a test with an emoji. Everything looked fine. The event saved. The ID returned. But when I restarted the server, that event was gone. Corrupted.&lt;/p&gt;

&lt;p&gt;The problem was string.length. An emoji like "🔥" is one character but four bytes. My offsets were wrong by three bytes. When the server rebuilt the index, it couldn't parse the event.&lt;/p&gt;

&lt;p&gt;The fix was Buffer.byteLength(line, 'utf8') instead of .length. That tiny change made everything work. Emojis, Chinese characters, everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I took away&lt;/strong&gt;&lt;br&gt;
Databases aren't magic. They're files. And indexes. And a lot of careful thinking about bytes.&lt;/p&gt;

&lt;p&gt;I also learned that the source of truth is never the index it's the log. The index is just a cache. If it disappears, you rebuild it. That changed how I think about caching in general.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I picked it&lt;/strong&gt;&lt;br&gt;
Because I finally understand what "write-ahead logging" means. I can explain it now, not as a buzzword, but as something I've debugged at 3am on a Tuesday while so many others are in deep sleep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task 2: Admin Teams Management API (Team Task)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;What It Was&lt;/strong&gt;&lt;br&gt;
Build a complete admin teams management system from scratch. Create, read, soft-delete teams. Invite members in batches. Generate secure tokens. Send emails. Track pending invitations. Revoke invites. Full CRUD with an invitation system.&lt;/p&gt;

&lt;p&gt;Sounds straightforward on paper. It wasn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
The admin portal needed internal teams to control access. Admins needed to create teams, invite members by email, and remove access when necessary. The Figma showed a teams list, a delete confirmation modal, and a full invite flow. Behind the scenes, this meant three new database tables, six API endpoints, email integration, secure token generation, and batch processing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I Approached It&lt;/strong&gt;&lt;br&gt;
I started with the database schema. &lt;code&gt;admin_teams&lt;/code&gt;, &lt;code&gt;team_memberships&lt;/code&gt;, &lt;code&gt;team_invitations&lt;/code&gt;. Foreign keys, status enums, timestamps. That part actually went smoothly.&lt;/p&gt;

&lt;p&gt;Then I wrote the service layer. &lt;code&gt;findAll&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;softDelete&lt;/code&gt;, &lt;code&gt;inviteMembers&lt;/code&gt;, &lt;code&gt;getInvitations&lt;/code&gt;, &lt;code&gt;revokeInvitation&lt;/code&gt;. Each method had its own quirks, but the real nightmare was &lt;code&gt;inviteMembers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The requirement: process up to 20 emails per request. Each email independently validated. If two fail, the other eighteen still send. Return a summary. Track failures. Send individual invites via email queue.&lt;/p&gt;

&lt;p&gt;What Broke and How I Fixed It&lt;br&gt;
The SHA-256 debacle. The spec demanded cryptographic tokens. Generate a raw token with crypto.randomBytes(32). Hash it with SHA-256. Store the hash. Send the raw token in the email link. When the user clicks, hash the incoming token and compare.&lt;/p&gt;

&lt;p&gt;I got this wrong a couple of times. If I remember very well one of the times I think I stored the raw token directly which is a security violation and on top of that pointless. I finally got it right but the URL parsing in the test kept failing because my environment variables weren't set properly during test execution. The test expected &lt;code&gt;https://seil.hng14.com&lt;/code&gt; but my .env had &lt;code&gt;https://staging.flowbrand.hng14.com&lt;/code&gt;. Took me an embarrassingly long time to realize the test was failing for the wrong reason.&lt;/p&gt;

&lt;p&gt;The batch processing race condition. When inviting multiple emails, I needed to check each email against existing pending invites and existing team memberships. But these checks weren't atomic. In theory, two simultaneous requests could race and create duplicate invites. I added proper checks and used database unique constraints as the final backstop.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;APP_URL&lt;/code&gt; vs &lt;code&gt;FRONTEND_URL&lt;/code&gt; confusion. The spec said &lt;code&gt;APP_URL&lt;/code&gt;. The codebase used &lt;code&gt;FRONTEND_URL&lt;/code&gt;. My invites were generating links to nowhere until our mentor Jeda helped me traced the environment variable chain and that is when I realized the mismatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Took Away&lt;/strong&gt;&lt;br&gt;
Always verify environment variables exist before using them. Fail fast with clear messages.&lt;/p&gt;

&lt;p&gt;Tests are not optional. My tests caught the SHA-256 bug, the URL parsing issue, and the batch failure handling. Without them, I would have shipped broken code.&lt;/p&gt;

&lt;p&gt;Batch operations need careful error handling. One failure shouldn't sink the whole ship.&lt;/p&gt;

&lt;p&gt;Read the existing codebase before writing new code. The &lt;code&gt;FRONTEND_URL&lt;/code&gt; vs &lt;code&gt;APP_URL&lt;/code&gt; lesson cost me an hour of head-scratching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I Picked This Task&lt;/strong&gt;&lt;br&gt;
It was my first major backend feature from scratch. No boilerplate, no copy-paste. Just me, the spec, and a deadline. It taught me more about NestJS, TypeORM, and secure token handling than any tutorial ever could.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
The HNG Internship doesn't hold your hand. It throws you into the deep end and trusts you'll figure out how to swim. Some days I was doggy-paddling. Some days I was drowning. But by the end, I learned how to navigate waters I never thought I'd enter.&lt;/p&gt;

&lt;p&gt;Those two tasks both broke me in different ways and I can say both have rebuilt me stronger.&lt;/p&gt;

&lt;p&gt;If you're doing this internship and struggling that is good because that's the point. Keep going. The panic you feel at 2 AM debugging a race condition is the price of admission to becoming an engineer who actually knows what they're doing.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>career</category>
      <category>database</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
