<?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: Mohamed Idris</title>
    <description>The latest articles on DEV Community by Mohamed Idris (@edriso).</description>
    <link>https://dev.to/edriso</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%2F542036%2F3d38f955-495f-4ee8-9445-db0d27f2fd7b.png</url>
      <title>DEV Community: Mohamed Idris</title>
      <link>https://dev.to/edriso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/edriso"/>
    <language>en</language>
    <item>
      <title>I made a swing boat that reacts to doom scrolling</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Sat, 25 Apr 2026 15:53:48 +0000</pubDate>
      <link>https://dev.to/edriso/i-made-a-swing-boat-that-reacts-to-doom-scrolling-1cmh</link>
      <guid>https://dev.to/edriso/i-made-a-swing-boat-that-reacts-to-doom-scrolling-1cmh</guid>
      <description>&lt;p&gt;When I was a kid, I tried the swing boat a few times and hated it. It made me dizzy. The kind of dizzy where you are not sure if it is fun anymore. You start slow, then someone keeps pushing, and before you know it you are too high and your stomach does not agree.&lt;/p&gt;

&lt;p&gt;I got that same feeling recently, but from scrolling.&lt;/p&gt;

&lt;p&gt;Doom scrolling is that thing you do when you open your phone for no reason and close it twenty minutes later having seen nothing worth remembering. Your finger goes up and down, up and down, the same motion as a swing. Your brain sits there getting rocked back and forth until it is numb. That is the brain rot part. Not dramatic, just slow and quiet. Your attention gets shorter. Your mood gets worse. You feel tired but you also cannot stop.&lt;/p&gt;

&lt;p&gt;I kept thinking about how the finger movement looks exactly like a swing. Up and down, rhythm, momentum. The more you do it, the harder it is to stop. Same physics, different damage.&lt;/p&gt;

&lt;p&gt;So I made a small thing to show that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;It is a red swing boat hanging in the dark. When you scroll, it swings. Keep scrolling and it goes higher. Stop, and it slowly dies down the way a real swing does. Short messages appear below the boat as the energy builds up. They start gentle. They do not stay that way.&lt;/p&gt;

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

&lt;p&gt;The whole thing is a single HTML file with no dependencies. The boat is an inline SVG so CSS and JavaScript can interact with it directly. The swing uses real pendulum physics, gravity and damping included, so it coasts and rocks naturally after you stop. Scroll speed feeds into the angular velocity, which means the harder you scroll the higher the swing goes.&lt;/p&gt;

&lt;p&gt;The scroll itself is captured with a &lt;code&gt;wheel&lt;/code&gt; event and &lt;code&gt;preventDefault&lt;/code&gt;, so the page never actually scrolls. There is nothing to read. Just the boat.&lt;/p&gt;

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

&lt;p&gt;Demo: &lt;a href="https://github.com/edriso/doomswing" rel="noopener noreferrer"&gt;github.com/edriso/doomswing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ux</category>
      <category>html</category>
    </item>
    <item>
      <title>My bot stopped sending questions the day Egypt turned on Daylight Saving Time</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Sat, 25 Apr 2026 08:16:24 +0000</pubDate>
      <link>https://dev.to/edriso/my-bot-stopped-sending-questions-the-day-egypt-turned-on-daylight-saving-time-59ce</link>
      <guid>https://dev.to/edriso/my-bot-stopped-sending-questions-the-day-egypt-turned-on-daylight-saving-time-59ce</guid>
      <description>&lt;p&gt;I built a Telegram bot that sends math questions to kids every day at 2:30 PM Egypt time. It had been live for two weeks, running every single day without a problem, questions going out on time, kids answering, streaks building up. Then recently I ran &lt;code&gt;/admin_health&lt;/code&gt; in the bot and saw &lt;strong&gt;0&lt;/strong&gt; scheduled questions. That's when I knew something was wrong and went digging through the logs.&lt;/p&gt;

&lt;p&gt;The last successful run was April 23. That night, Egypt turned on Daylight Saving Time.&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%2Fdro3h8q7eu7eqkg1nx98.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%2Fdro3h8q7eu7eqkg1nx98.png" alt=" " width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me walk you through how the whole thing worked, what broke, and how I fixed it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the bot schedules questions
&lt;/h2&gt;

&lt;p&gt;The bot has two main daily jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;01:30 AM Cairo&lt;/strong&gt;: prepare today's questions for every user (pick 3 questions based on each kid's weak topics, save them to the database)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2:30 PM Cairo&lt;/strong&gt;: send the first question to everyone&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I use a library called &lt;code&gt;node-cron&lt;/code&gt; for scheduling. It supports timezones, so I just tell it "run this at 00:30 Cairo time" and it figures out the UTC equivalent automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30 0 * * *&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&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;await&lt;/span&gt; &lt;span class="nf"&gt;prepareScheduledQuestions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Africa/Cairo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How "Cairo time" works in the code
&lt;/h3&gt;

&lt;p&gt;The bot server runs on Railway (cloud), so it lives in UTC. Every time I need to know "what day is it in Cairo?", I use this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;todayCairoAsUtcMidnight&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get today's date as a string in Cairo timezone, e.g. "2026-04-23"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-CA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timeZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Africa/Cairo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;numeric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2-digit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="c1"&gt;// Return that date as UTC midnight so we can compare with database values&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dateStr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;T00:00:00.000Z&lt;/span&gt;&lt;span class="dl"&gt;'&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;So "today in Cairo" becomes a fixed timestamp I can store in the database and compare against later. A question prepared at 01:30 AM Cairo gets tagged with &lt;code&gt;2026-04-23T00:00:00.000Z&lt;/code&gt;. When the 2:30 PM cron runs, it looks up questions tagged with that same date. If they match, the question gets sent.&lt;/p&gt;

&lt;p&gt;This works great as long as Cairo is always UTC+2.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Daylight Saving Time?
&lt;/h2&gt;

&lt;p&gt;DST is when a country moves its clocks forward by 1 hour in summer to make better use of daylight. Egypt reinstated DST in 2023 after not using it for about 10 years.&lt;/p&gt;

&lt;p&gt;In Egypt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Last Friday of April at midnight&lt;/strong&gt; → clocks jump from 00:00 to 01:00 (spring forward)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Last Thursday of October at midnight&lt;/strong&gt; → clocks go back from 01:00 to 00:00 (fall back)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key phrase is &lt;strong&gt;"clocks jump from 00:00 to 01:00"&lt;/strong&gt;. That means 00:30 literally does not exist on that night.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;My prepare-questions cron was set to run at &lt;strong&gt;00:30 Cairo time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On April 24, 2026 (the DST transition day), at midnight Cairo, clocks skipped forward one hour. The time went from &lt;code&gt;00:00&lt;/code&gt; directly to &lt;code&gt;01:00&lt;/code&gt;. There was no &lt;code&gt;00:30&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node-cron&lt;/code&gt; saw that 00:30 didn't exist that night and &lt;strong&gt;silently skipped the job&lt;/strong&gt;. No error, no warning, nothing in the logs. But it gets worse. After that skip, node-cron's internal scheduler got into a broken state. It was not just the prepare job that stopped. Every single cron job stopped firing. The 2:30 PM send job never ran on April 24. Or April 25. The bot process was alive on Railway, no crashes, no restarts, just complete silence for two days.&lt;/p&gt;

&lt;p&gt;Here are the actual logs. Everything stops on April 23:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[2026-04-22T22:30:00.006Z] [INFO] [CRON] Preparing daily questions...
[2026-04-22T22:30:31.408Z] [INFO] Prepared adaptive questions for 9 users
[2026-04-23T12:30:00.025Z] [INFO] [CRON] Sending first question...
[2026-04-23T12:30:25.042Z] [INFO] First question sent {"sent":8,"failed":1,"total":9}
[2026-04-23T17:30:00.016Z] [INFO] [CRON] Sending reminders...
[2026-04-23T17:30:05.120Z] [INFO] Reminders sent {"sent":8,"total":9}

(silence after this)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;22:30 UTC&lt;/code&gt; = &lt;code&gt;00:30 Cairo (UTC+2)&lt;/code&gt;, and that was the last time questions were prepared. After that, the clocks changed and 00:30 disappeared.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why there were no errors
&lt;/h2&gt;

&lt;p&gt;This is the sneaky part. &lt;code&gt;node-cron&lt;/code&gt; doesn't throw an error when a scheduled time is skipped due to DST. And when the scheduler breaks internally, it also does not throw an error. The bot process just keeps running, healthy from Railway's point of view, with zero indication that all the scheduled work stopped.&lt;/p&gt;

&lt;p&gt;No crash to investigate. No alert to wake you up. Just kids not getting their questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fix 1: Move the cron to a safe time
&lt;/h2&gt;

&lt;p&gt;The simplest fix: change &lt;code&gt;00:30&lt;/code&gt; to &lt;code&gt;01:30&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Egypt's clocks spring from &lt;code&gt;00:00&lt;/code&gt; to &lt;code&gt;01:00&lt;/code&gt;, so &lt;code&gt;01:30&lt;/code&gt; always exists, even on DST transition day. Problem solved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (broken on DST spring-forward day):&lt;/span&gt;
&lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30 0 * * *&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Africa/Cairo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// After (safe):&lt;/span&gt;
&lt;span class="nx"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;30 1 * * *&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Africa/Cairo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more thing: on the fall-back day in October, clocks go from &lt;code&gt;01:00&lt;/code&gt; back to &lt;code&gt;00:00&lt;/code&gt;, so &lt;code&gt;01:30&lt;/code&gt; actually happens twice that night. That means the job runs twice. But that is totally fine, because at the start of &lt;code&gt;prepareScheduledQuestions()&lt;/code&gt; there is a check: if a user already has questions prepared for today, skip them. So the second run just finds everyone already done and exits. No duplicates, no problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fix 2: Add a fallback inside the send job
&lt;/h2&gt;

&lt;p&gt;The cron time fix handles DST. But what if the prepare job fails for any other reason, like a server hiccup, a deploy at the wrong time, whatever?&lt;/p&gt;

&lt;p&gt;I added one line at the top of the send-questions job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendFirstQuestion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If questions weren't prepared for any reason, prepare them now before sending&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;prepareScheduledQuestions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// ... rest of the send logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;prepareScheduledQuestions()&lt;/code&gt; already skips users who have questions today, so calling it here costs nothing on a normal day. But on a broken day, it saves everyone from getting nothing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The lesson
&lt;/h2&gt;

&lt;p&gt;If your cron jobs use a timezone that observes DST, avoid scheduling at times that get skipped during the spring-forward transition. In Egypt that means avoid &lt;code&gt;00:01&lt;/code&gt; through &lt;code&gt;00:59&lt;/code&gt;. Use &lt;code&gt;01:30&lt;/code&gt; or later to be safe.&lt;/p&gt;

&lt;p&gt;More generally: &lt;strong&gt;cron + timezones is a place where things can go silently wrong&lt;/strong&gt;. The job doesn't crash, there's no alert, users just don't hear from your app. Always add a fallback or at least an explicit log when your main jobs find zero work to do. That's usually a sign something upstream failed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prepared&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No questions prepared, double check the prepare-questions job ran today&lt;/span&gt;&lt;span class="dl"&gt;'&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;That one log line would have caught this immediately.&lt;/p&gt;




&lt;p&gt;The bot is now fixed and sending questions again. And next April, when Egypt springs forward, it'll handle it quietly.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;A question:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Someone may ask: what if you really wanted the job to always run at exactly 00:30 Cairo, no matter what happens to the clock?&lt;/p&gt;

&lt;p&gt;Short answer: you can't. Not on spring-forward night.&lt;/p&gt;

&lt;p&gt;00:30 Cairo on that night does not exist. The clock jumps from 00:00 directly to 01:00. There is no UTC value that maps to 00:30 Cairo on that specific night. It was erased. No library, no trick, no workaround can schedule something at a time that literally never happens.&lt;/p&gt;

&lt;p&gt;The closest you can get is one of two things.&lt;/p&gt;

&lt;p&gt;First option is what we already did: move to 01:30. It always exists, even on the transition night. On 364 days a year it runs at 01:30 Cairo. On that one spring-forward night it also runs at 01:30 Cairo, which is just one hour later than you wanted. Not a big deal.&lt;/p&gt;

&lt;p&gt;Second option is to schedule at two UTC times, one for winter and one for summer. Winter Cairo is UTC+2, so 00:30 Cairo = 22:30 UTC. Summer Cairo is UTC+3, so 00:30 Cairo = 21:30 UTC. You run both. Since the prepare function skips users who already have questions today, only one of the two actually does any work on a normal night. On the transition night, 22:30 UTC lands at 01:30 Cairo so you again get one hour late, but questions are still prepared. This gets you 00:30 on all regular nights in both seasons.&lt;/p&gt;

&lt;p&gt;But honestly the real safety net is the fallback we added inside the send job. Even if the prepare cron runs late, or gets skipped, or breaks entirely, questions get prepared right before they are sent at 2:30 PM. That is what actually protects users, not the exact minute the prepare job fires.&lt;/p&gt;

</description>
      <category>node</category>
      <category>cron</category>
      <category>timezone</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Stop arguing about formatting in code reviews. Use Husky and lint-staged instead.</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Fri, 24 Apr 2026 19:52:09 +0000</pubDate>
      <link>https://dev.to/edriso/stop-arguing-about-formatting-in-code-reviews-use-husky-and-lint-staged-instead-1lp</link>
      <guid>https://dev.to/edriso/stop-arguing-about-formatting-in-code-reviews-use-husky-and-lint-staged-instead-1lp</guid>
      <description>&lt;p&gt;If your team has ever left a comment like "missing semicolon" or "wrong quote style" on a pull request, this post is for you.&lt;/p&gt;

&lt;p&gt;Formatting is not a code review topic. It should be handled automatically before the code even reaches a PR. Here is how to do that cleanly using Husky and lint-staged.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we actually solving?
&lt;/h2&gt;

&lt;p&gt;The problem is simple: developers format code differently, editors have different defaults, and without enforcement, you end up with inconsistent style that creates noisy diffs and unnecessary review comments.&lt;/p&gt;

&lt;p&gt;The goal is to auto-format and auto-lint staged files right before every commit, so bad formatting never reaches the repo.&lt;/p&gt;

&lt;p&gt;Two tools make this easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prettier&lt;/strong&gt; handles formatting (spacing, quotes, semicolons, line length)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint&lt;/strong&gt; handles code quality (unused variables, missing dependencies, bad patterns)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Husky&lt;/strong&gt; lets you run scripts automatically on git events like pre-commit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lint-staged&lt;/strong&gt; runs those scripts only on staged files, not your entire codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running tools on the full project on every commit would be slow. lint-staged keeps it fast by scoping to only what you changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install the tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do not already have Prettier and ESLint set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; prettier eslint eslint-config-prettier eslint-plugin-prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;eslint-config-prettier&lt;/code&gt; disables ESLint rules that conflict with Prettier. &lt;code&gt;eslint-plugin-prettier&lt;/code&gt; makes ESLint report Prettier violations as lint errors. Without these two, ESLint and Prettier will fight each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Initialize Husky
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;.husky/&lt;/code&gt; folder and adds a &lt;code&gt;prepare&lt;/code&gt; script to your &lt;code&gt;package.json&lt;/code&gt;:&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="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"prepare"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"husky"&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;The &lt;code&gt;prepare&lt;/code&gt; script runs automatically on &lt;code&gt;npm install&lt;/code&gt;. That means anyone who clones your repo and installs dependencies gets the pre-commit hook set up without doing anything manually. This is the key to making it work across a team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set up the pre-commit hook
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;.husky/pre-commit&lt;/code&gt; and replace whatever is in it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is all. Every time you run &lt;code&gt;git commit&lt;/code&gt;, Husky will run lint-staged before the commit goes through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure lint-staged
&lt;/h2&gt;

&lt;p&gt;Add this to your &lt;code&gt;package.json&lt;/code&gt;:&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="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"src/**/*.{js,jsx,ts,tsx}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint --fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"src/**/*.{css,json,md}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write"&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;This says: on staged JS and JSX files inside &lt;code&gt;src/&lt;/code&gt;, run ESLint with auto-fix. On staged CSS, JSON, and Markdown files, run Prettier.&lt;/p&gt;

&lt;p&gt;Why split them? Because &lt;code&gt;eslint-plugin-prettier&lt;/code&gt; already runs Prettier internally when you run &lt;code&gt;eslint --fix&lt;/code&gt; on JS files, so you do not need to run both. For CSS and other file types, Prettier handles it directly since ESLint does not cover them.&lt;/p&gt;

&lt;p&gt;If you are working on a plain HTML or CSS project without ESLint, simplify to just:&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="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"**/*.{html,css,js,json,md}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write"&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;h2&gt;
  
  
  Step 5: Add a .prettierignore file
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.prettierignore&lt;/code&gt; in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist/
node_modules/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents Prettier from formatting compiled or generated output. Without this, it might reformat your minified CSS or bundled JS, which is not what you want.&lt;/p&gt;

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

&lt;p&gt;You make changes to a few files, stage them with &lt;code&gt;git add&lt;/code&gt;, and run &lt;code&gt;git commit&lt;/code&gt;. Husky fires the pre-commit hook. lint-staged checks which staged files match your patterns and runs the tools only on those. If ESLint finds an error it cannot auto-fix, the commit is blocked and you see the error. If everything passes, the commit goes through with clean, formatted code.&lt;/p&gt;

&lt;p&gt;The first time you set this up, you will probably want to run a full format pass on the whole project so everything starts from a clean state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prettier &lt;span class="nt"&gt;--write&lt;/span&gt; &lt;span class="s2"&gt;"src/**/*.{js,jsx,css,json}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit that as a single formatting commit, then the pre-commit hook keeps things clean going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code integration (the finishing touch)
&lt;/h2&gt;

&lt;p&gt;The pre-commit hook is your safety net. But you can also make formatting happen as you type by adding a &lt;code&gt;.vscode/settings.json&lt;/code&gt; to your project:&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;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"source.fixAll.eslint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&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;span class="nl"&gt;"eslint.validate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"javascript"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"javascriptreact"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files.autoSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"off"&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;With this, every time you hit save, VS Code runs Prettier and ESLint automatically. By the time you stage your files, they are already formatted. The Husky hook just confirms nothing slipped through.&lt;/p&gt;

&lt;p&gt;Commit this file to the repo so the whole team gets the same editor behavior without any manual setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No more formatting comments in code reviews&lt;/li&gt;
&lt;li&gt;Clean diffs that show only real changes&lt;/li&gt;
&lt;li&gt;Commits that are always consistent, regardless of who made them&lt;/li&gt;
&lt;li&gt;New team members get the full setup just by running &lt;code&gt;npm install&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It takes about ten minutes to set up and saves hours of back-and-forth over style issues. Worth it.&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Resume Update!</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Thu, 23 Apr 2026 16:01:33 +0000</pubDate>
      <link>https://dev.to/edriso/resume-update-1f0f</link>
      <guid>https://dev.to/edriso/resume-update-1f0f</guid>
      <description>&lt;p&gt;A while back I shared that I built my resume as a website so I can update it in one place without re-uploading files or changing links everywhere.&lt;/p&gt;

&lt;p&gt;Now that I'm looking for a new job, I ran into a new problem; I wanted to tailor my resume depending on the role I'm applying to. Sending the same resume to a Magento recruiter and a frontend recruiter doesn't really make sense.&lt;/p&gt;

&lt;p&gt;So I fixed that by adding a query param to the resume URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;edriso.github.io?r=fullstack
edriso.github.io?r=frontend
edriso.github.io?r=php
edriso.github.io?r=magento

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each one shows a different version; different title, different bio, different skills order 😃.&lt;/p&gt;

&lt;p&gt;And it saves to localStorage, so if the recruiter refreshes the page or comes back later without the param, they still see the right version. &lt;/p&gt;

&lt;p&gt;Same thing on my portfolio site. The resume link in the footer automatically includes the right role param based on which version of the portfolio the recruiter is viewing.&lt;/p&gt;

&lt;p&gt;One link per recruiter. No confusion.&lt;/p&gt;

&lt;p&gt;Alhamdulillah 🙌&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Undo a Git Commit Without Losing History</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Thu, 23 Apr 2026 13:43:41 +0000</pubDate>
      <link>https://dev.to/edriso/how-to-undo-a-git-commit-without-losing-history-3ifp</link>
      <guid>https://dev.to/edriso/how-to-undo-a-git-commit-without-losing-history-3ifp</guid>
      <description>&lt;p&gt;We've all been there — you made a commit, pushed it, and then realized: &lt;em&gt;that was a mistake&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The good news? Git has a safe way to undo it without rewriting history.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You might think of using &lt;code&gt;git reset&lt;/code&gt; to go back in time. But if you've already pushed the commit to a shared branch, resetting and force-pushing can cause problems for everyone else on the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Better Way: &lt;code&gt;git revert&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git revert&lt;/code&gt; creates a &lt;strong&gt;new commit&lt;/strong&gt; that undoes the changes from a previous commit. Your history stays intact — you just add an undo step on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Do It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Find the commit you want to undo&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a8636a4 Tailor portfolio for e-commerce role
d56677a Fix hover effect
5315182 Add new project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the hash of the commit you want to revert (e.g. &lt;code&gt;a8636a4&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Revert it&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git revert a8636a4 &lt;span class="nt"&gt;--no-edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a8636a4&lt;/code&gt; — the commit hash you want to undo&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--no-edit&lt;/code&gt; — skips the editor and uses the default revert message&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git will create a new commit like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bf880c5 Revert "Tailor portfolio for e-commerce role"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Your mistake is undone and your history is clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use &lt;code&gt;git revert&lt;/code&gt; vs &lt;code&gt;git reset&lt;/code&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;git revert&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;git reset&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Creates a new commit&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safe for shared branches&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rewrites history&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If the commit is already pushed, use &lt;code&gt;git revert&lt;/code&gt;. If it's only local, &lt;code&gt;git reset&lt;/code&gt; is fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See your commits&lt;/span&gt;
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;

&lt;span class="c"&gt;# Revert the one you don't want&lt;/span&gt;
git revert &amp;lt;commit-hash&amp;gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, safe, and no drama. That's the Git way.&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The 3-Second Rule: How to Write a Freelance Proposal That Gets Read (and Gets Replies)</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Wed, 22 Apr 2026 17:27:58 +0000</pubDate>
      <link>https://dev.to/edriso/the-3-second-rule-how-to-write-a-freelance-proposal-that-gets-read-and-gets-replies-3l9g</link>
      <guid>https://dev.to/edriso/the-3-second-rule-how-to-write-a-freelance-proposal-that-gets-read-and-gets-replies-3l9g</guid>
      <description>&lt;p&gt;A friend told you to use "a 3-second role point" in your proposal. Good advice. But what does that actually mean?&lt;/p&gt;

&lt;p&gt;This post breaks it down in plain English — with real examples, clear comparisons, and things you can use today on Upwork, Freelancer, Toptal, or any similar platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why "3 Seconds" at All?
&lt;/h2&gt;

&lt;p&gt;When a client posts a job on Upwork, they might get 20, 50, or even 100 proposals. They are not reading every word. They are &lt;strong&gt;scanning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Studies and freelance coaches consistently say the same thing: &lt;strong&gt;a client decides in the first 3 to 8 seconds whether your proposal is worth reading — or worth skipping.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those first few seconds happen at the very first line of your proposal. That is where you either win their attention or lose it forever.&lt;/p&gt;

&lt;p&gt;This is the "3-second rule": your opening must be so relevant, so specific, and so interesting that the client stops scrolling and reads the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Biggest Mistake Freelancers Make
&lt;/h2&gt;

&lt;p&gt;Before we get to the good stuff, let us look at what most people write.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A typical (losing) proposal opening:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hello, my name is Ahmed and I am a full-stack developer with 5 years of experience. I have worked with React, Node.js, MongoDB, and more. I am very passionate about coding and I believe I am the perfect candidate for this job..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sound familiar? This is what 80% of proposals look like.&lt;/p&gt;

&lt;p&gt;The client does not care about your name in the first sentence. They do not care about your years of experience yet. They care about &lt;strong&gt;their problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You spent the first 3 seconds talking about yourself. They moved on.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 3-Second Rule Point: Make It About Them First
&lt;/h2&gt;

&lt;p&gt;Your opening line — your "3-second point" — should do one thing: &lt;strong&gt;show the client that you actually read their job post and you understand their specific problem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not a general problem. Their specific, stated problem.&lt;/p&gt;

&lt;p&gt;Here is the formula for that opening line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Specific observation about their project] + [How you can help with that specific thing]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. One or two sentences. Sharp and relevant.&lt;/p&gt;




&lt;h2&gt;
  
  
  Good vs Bad: Side by Side
&lt;/h2&gt;

&lt;p&gt;Let us look at a real job post and compare proposals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job Post:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I need a developer to fix my WooCommerce checkout page. Customers are abandoning at the payment step — I think it is a PayPal integration bug. My site is slow too. Budget: $200."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Bad proposal opening:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hi, I am a WordPress and WooCommerce expert with 6 years of experience. I can help you with your website. I am very hardworking and deliver on time. Please check my profile."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What is wrong here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is generic. This could be sent to any WooCommerce job.&lt;/li&gt;
&lt;li&gt;It does not mention the PayPal bug.&lt;/li&gt;
&lt;li&gt;It does not mention the checkout abandonment problem.&lt;/li&gt;
&lt;li&gt;It does not mention the slow site.&lt;/li&gt;
&lt;li&gt;The client feels like you did not read their post at all.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Good proposal opening:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Checkout abandonment at the PayPal step is almost always a redirect loop or a mismatched IPN URL — I have fixed this exact issue three times this month. I can also audit your page speed in the same session since slow checkout pages make abandonment worse."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What is different here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It names the exact problem: checkout abandonment.&lt;/li&gt;
&lt;li&gt;It names the exact tool: PayPal.&lt;/li&gt;
&lt;li&gt;It shows specific knowledge: "redirect loop or mismatched IPN URL" — this is credible.&lt;/li&gt;
&lt;li&gt;It connects the two problems they mentioned (PayPal bug + slow site) in one sentence.&lt;/li&gt;
&lt;li&gt;The client thinks: "This person actually read what I wrote."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is 3 seconds well spent.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Full Proposal Structure (After the Hook)
&lt;/h2&gt;

&lt;p&gt;The 3-second opening is just the beginning. Here is the full structure that converts attention into replies:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Hook (Seconds 1-3)
&lt;/h3&gt;

&lt;p&gt;Your one or two sentence opener. Specific, relevant, and about them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Bridge (Your Relevant Experience)
&lt;/h3&gt;

&lt;p&gt;Now — and only now — you talk about yourself. But keep it tied to their problem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I have been building WooCommerce sites for 4 years, and payment gateway bugs are one of the most common things I fix. Here is a similar case: a client's Stripe checkout was silently failing and costing them $3,000/month. I found it in under an hour."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice: one data point, one number, tied directly to their situation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Plan (What You Will Do)
&lt;/h3&gt;

&lt;p&gt;Tell them how you will solve it. Not in vague words — in concrete steps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Here is my plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reproduce the checkout error and check the PayPal IPN logs (1-2 hours)&lt;/li&gt;
&lt;li&gt;Fix the integration and test on staging (1-2 hours)&lt;/li&gt;
&lt;li&gt;Run a quick speed audit using GTmetrix and apply the top 3 fixes (1 hour)&lt;/li&gt;
&lt;li&gt;Full test before handover"&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;This builds trust. It shows you have a process, not just "I will figure it out."&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Proof (Why Trust You)
&lt;/h3&gt;

&lt;p&gt;A portfolio link, a relevant result, or a short testimonial quote. Keep it to one thing — do not list 10 projects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Here is a WooCommerce project where I fixed a similar Stripe issue: [link]"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. The Call to Action (CTA)
&lt;/h3&gt;

&lt;p&gt;End with a clear, low-pressure next step. Do not just say "let me know."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Happy to jump on a 15-minute call to look at the issue together — no cost, just to confirm I can help before you commit. Or if you prefer, send me a test account and I can start today."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Full Example: Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Here is a complete proposal for the WooCommerce job above (under 200 words):&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Checkout abandonment at the PayPal step is almost always a redirect loop or a mismatched IPN URL — I have fixed this exact issue three times this month.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I have been building WooCommerce stores for 4 years. Last month I helped a client in a similar situation: their PayPal checkout was silently failing for mobile users only, and they had no idea. I found it in the PayPal sandbox logs in about an hour.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My plan for your project:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;1. Reproduce the error and check your PayPal IPN and webhook settings&lt;/em&gt;&lt;br&gt;
&lt;em&gt;2. Fix the bug and test on staging&lt;/em&gt;&lt;br&gt;
&lt;em&gt;3. Run a GTmetrix speed audit and apply the top fixes&lt;/em&gt;&lt;br&gt;
&lt;em&gt;4. Deliver with a short Loom video explaining what I found and fixed&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Portfolio: [link to similar WooCommerce project]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am available to start today. Want to do a quick 10-minute call so I can see the error myself before we start? Or just send me a staging login and I will take a look.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Clean. Specific. Confident. Under 200 words.&lt;/p&gt;




&lt;h2&gt;
  
  
  More Hook Examples You Can Adapt
&lt;/h2&gt;

&lt;p&gt;Here are 5 quick openers for different situations. Notice each one names a specific detail from a hypothetical job post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a React performance job:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A 4-second load time on the dashboard is almost always a missing memo or a useEffect firing too often — both are straightforward to diagnose with React DevTools."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;For a landing page redesign:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If your current page is converting at under 2%, the problem is usually the headline or the CTA placement — the design is secondary. I would start there before touching anything visual."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;For a Node.js API bug:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A race condition on concurrent requests is one of the trickier Node bugs because it does not always reproduce in dev. I would start with your async/await error handling and check if you have any unhandled promise rejections in production logs."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;For a WordPress migration:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Moving 1,200 posts from Wix to WordPress without losing SEO rankings is totally doable if you set up 301 redirects correctly from day one — I have done three migrations like this in the last two months."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;For a Python scraping job:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If the site blocks you after 50 requests, it is almost certainly rate-limiting by IP. Rotating proxies plus random delays between requests fixes this 90% of the time."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Things That Kill Good Proposals
&lt;/h2&gt;

&lt;p&gt;Even with a great hook, these common mistakes will lose you the job:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Too long.&lt;/strong&gt; If your proposal is over 300 words, most clients will not finish reading it. Say less, say it better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy-paste feel.&lt;/strong&gt; Clients can tell when you sent the same proposal 50 times. Even one tiny detail from their post makes it feel personal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No proof.&lt;/strong&gt; Saying "I am an expert" means nothing. One relevant link, one number, one past result — that means something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weak ending.&lt;/strong&gt; "Looking forward to your response" is not a CTA. Give them something to do: a question to answer, a call to book, a next step to take.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Starting with "I."&lt;/strong&gt; The very first word of your proposal should never be "I." It signals immediately that you are about to talk about yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Checklist Before You Send
&lt;/h2&gt;

&lt;p&gt;Before hitting send on any proposal, run through this list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Does my first sentence name something specific from their job post?&lt;/li&gt;
&lt;li&gt;[ ] Did I avoid starting with my name or years of experience?&lt;/li&gt;
&lt;li&gt;[ ] Did I explain what I will do, not just that I can do it?&lt;/li&gt;
&lt;li&gt;[ ] Did I include one concrete result or proof point?&lt;/li&gt;
&lt;li&gt;[ ] Did I end with a clear, specific next step?&lt;/li&gt;
&lt;li&gt;[ ] Is it under 250 words?&lt;/li&gt;
&lt;li&gt;[ ] Does it sound like a human wrote it, not a template?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If all boxes are checked, send it.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The "3-second rule point" your friend mentioned is simply this: &lt;strong&gt;your first sentence must prove you read the job post and understand the client's actual problem — before you say a single word about yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Structure your proposal like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hook&lt;/strong&gt; — one specific, relevant sentence about their problem&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bridge&lt;/strong&gt; — your experience, tied to their situation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; — concrete steps, not vague promises&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof&lt;/strong&gt; — one link or result&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTA&lt;/strong&gt; — a simple, clear next step&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most freelancers write about themselves. You write about the client. That is the difference.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What is the hardest part of writing proposals for you? Drop a comment — I read every one.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.upwork.com/resources/how-to-create-a-proposal-that-wins-jobs" rel="noopener noreferrer"&gt;How To Create a Proposal That Wins Jobs - Upwork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gigradar.io/blog/25-upwork-proposal-openers-that-get-replies" rel="noopener noreferrer"&gt;25 Upwork Proposal Openers That Get Replies Fast - GigRadar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freelancewitherica.substack.com/p/get-your-upwork-proposals-opened" rel="noopener noreferrer"&gt;The Secret Formula to Getting Your Proposals ACTUALLY SEEN - Freelance with Erica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/upwork-proposal-writing-hacks-3-steps-rule14-case-studies/" rel="noopener noreferrer"&gt;Upwork Proposal Writing Hacks (3-Step Rule) - Udemy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getmany.com/blog/7-upwork-proposal-sample-ideas-to-boost-your-success-in-2026" rel="noopener noreferrer"&gt;7 Upwork Proposal Sample Ideas to Boost Your Success - Getmany&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tymora.io/blog/how-to-write-an-upwork-proposal-2025" rel="noopener noreferrer"&gt;How to Write a Winning Upwork Proposal - Tymora&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>If You Were a Server: How to Detect Issues and Keep Things Running Smoothly</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Wed, 22 Apr 2026 17:26:15 +0000</pubDate>
      <link>https://dev.to/edriso/if-you-were-a-server-how-to-detect-issues-and-keep-things-running-smoothly-48dm</link>
      <guid>https://dev.to/edriso/if-you-were-a-server-how-to-detect-issues-and-keep-things-running-smoothly-48dm</guid>
      <description>&lt;p&gt;Here is a question that often pops up in senior web developer and backend interviews:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"If you were a server, how would you detect that you're having issues, and what would you do next to make things run smoothly?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first, it sounds a little weird. &lt;em&gt;Be a server?&lt;/em&gt; But that is actually the whole point. The interviewer wants to know if you can &lt;strong&gt;think like infrastructure&lt;/strong&gt; — can you see problems before they become disasters, and do you know how to respond?&lt;/p&gt;

&lt;p&gt;This post breaks it all down in simple English. Whether you are a junior developer hearing these concepts for the first time, or someone preparing for a senior interview, you will walk away with a solid mental model.&lt;/p&gt;




&lt;h2&gt;
  
  
  First: What Is the Question Really Asking?
&lt;/h2&gt;

&lt;p&gt;The question is covering two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Detection&lt;/strong&gt; — How does a server (or you, the developer/SRE watching it) know something is wrong?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response&lt;/strong&gt; — What actions do you take to fix it or at least keep things stable?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it like being a doctor for your own body. You check your temperature, blood pressure, and pulse. If something is off, you take medicine, rest, or call a specialist. Servers work the same way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: How Does a Server Detect It Has Issues?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Four Core Vitals
&lt;/h3&gt;

&lt;p&gt;Just like a doctor checks your basic vitals, a server has its own set of core health signals. These are the first things to look at.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. CPU Usage
&lt;/h4&gt;

&lt;p&gt;CPU (Central Processing Unit) is the brain of your server. It handles every calculation, request, and operation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Healthy:&lt;/strong&gt; Under 60-70% usage during normal load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warning:&lt;/strong&gt; Consistently above 80%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical:&lt;/strong&gt; Sustained 90%+ means your server is struggling to breathe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When CPU is maxed out, your server starts slowing down responses, queuing requests, or dropping them entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check it:&lt;/strong&gt; &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;htop&lt;/code&gt;, &lt;code&gt;vmstat&lt;/code&gt;, or any cloud monitoring dashboard like AWS CloudWatch or Datadog.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Memory (RAM) Usage
&lt;/h4&gt;

&lt;p&gt;Memory is your server's short-term workspace. Every running process uses RAM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Healthy:&lt;/strong&gt; Enough free RAM to handle spikes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warning:&lt;/strong&gt; When RAM fills up, your OS starts using &lt;strong&gt;swap&lt;/strong&gt; — which is disk space acting as fake RAM. Disk is &lt;strong&gt;much&lt;/strong&gt; slower than RAM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical:&lt;/strong&gt; If swap fills up too, processes start crashing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common mistake is ignoring memory leaks — situations where an application keeps grabbing more memory and never releasing it. Over time, this silently kills your server.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Disk Usage and I/O
&lt;/h4&gt;

&lt;p&gt;Disk usage is how much of your storage is full. Disk I/O is how fast data is being read and written.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best practice:&lt;/strong&gt; Keep at least 20-30% disk space free at all times.&lt;/li&gt;
&lt;li&gt;A full disk can crash your database, stop logging, and break deployments.&lt;/li&gt;
&lt;li&gt;High disk I/O (lots of reads/writes happening at once) can make everything slow, even if CPU and RAM look fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Network Bandwidth
&lt;/h4&gt;

&lt;p&gt;Your server talks to the outside world through the network. If the pipe gets clogged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests take longer to arrive and respond.&lt;/li&gt;
&lt;li&gt;Large file uploads or downloads can saturate the connection.&lt;/li&gt;
&lt;li&gt;You may see packet loss — data literally gets dropped mid-transfer.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Beyond the Core Vitals: Application-Level Signals
&lt;/h3&gt;

&lt;p&gt;The four core vitals tell you about the &lt;strong&gt;hardware&lt;/strong&gt;. But you also need to watch what your &lt;strong&gt;application&lt;/strong&gt; is doing.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Response Time / Latency
&lt;/h4&gt;

&lt;p&gt;How long does your server take to respond to a request?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A healthy API might respond in 100ms.&lt;/li&gt;
&lt;li&gt;If latency jumps to 2-3 seconds, something is wrong — maybe a slow database query, a blocked thread, or an overloaded service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; Users notice latency before they notice anything else. A slow page feels broken.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Error Rate
&lt;/h4&gt;

&lt;p&gt;What percentage of your requests are returning errors?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5xx errors (500, 502, 503, 504) mean &lt;strong&gt;your server is the problem&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If your error rate goes from 0.1% to 5%, something just broke.&lt;/li&gt;
&lt;li&gt;Spikes in 4xx errors (404, 403) can also signal broken deployments or misconfigured routes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. Throughput / Request Rate
&lt;/h4&gt;

&lt;p&gt;How many requests per second is your server handling?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sudden &lt;strong&gt;drop&lt;/strong&gt; in traffic can be as alarming as a spike — it might mean your server is down and clients are not even reaching it.&lt;/li&gt;
&lt;li&gt;A sudden &lt;strong&gt;spike&lt;/strong&gt; might mean a traffic surge, a bot attack, or a viral moment — all of which need different responses.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Health Checks: The Server Checking Itself
&lt;/h3&gt;

&lt;p&gt;Modern servers do not wait for humans to notice something is wrong. They &lt;strong&gt;self-report&lt;/strong&gt; through health check endpoints.&lt;/p&gt;

&lt;p&gt;There are two main types used in systems like Kubernetes:&lt;/p&gt;

&lt;h4&gt;
  
  
  Liveness Probe
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;"Am I still alive?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a simple check: is the process running at all? If a liveness probe fails, the orchestrator (like Kubernetes) will &lt;strong&gt;restart&lt;/strong&gt; the container.&lt;/p&gt;

&lt;p&gt;Example endpoint: &lt;code&gt;GET /health/live&lt;/code&gt; → returns &lt;code&gt;200 OK&lt;/code&gt; if running.&lt;/p&gt;

&lt;h4&gt;
  
  
  Readiness Probe
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;"Am I ready to receive traffic?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is more nuanced: is the server running &lt;strong&gt;and&lt;/strong&gt; fully ready to handle requests? Maybe it is warming up a cache, waiting for a database connection, or doing startup migrations.&lt;/p&gt;

&lt;p&gt;If a readiness probe fails, the load balancer &lt;strong&gt;stops sending traffic&lt;/strong&gt; to that instance — without killing it. Once it recovers, traffic resumes.&lt;/p&gt;

&lt;p&gt;Example endpoint: &lt;code&gt;GET /health/ready&lt;/code&gt; → checks DB connection, cache, etc.&lt;/p&gt;




&lt;h3&gt;
  
  
  Logging: The Server's Diary
&lt;/h3&gt;

&lt;p&gt;Logs are your best friend when something goes wrong. A server should write meaningful logs that tell a story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structured logging&lt;/strong&gt; means logging in a consistent format (usually JSON) so machines can read it:&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;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-04-22T10:30:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Database connection failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_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;"abc-123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&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;Without good logs, debugging is like trying to solve a crime with no evidence. With good logs, you can trace exactly what happened, when, and why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log levels&lt;/strong&gt; to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DEBUG&lt;/code&gt; — detailed developer info (not for production usually)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;INFO&lt;/code&gt; — normal operations ("User logged in")&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WARN&lt;/code&gt; — something is off but not broken yet&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ERROR&lt;/code&gt; — something broke, needs attention&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FATAL&lt;/code&gt; / &lt;code&gt;CRITICAL&lt;/code&gt; — the server cannot continue&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Alerting: Getting Notified Before It's Too Late
&lt;/h3&gt;

&lt;p&gt;Monitoring without alerting is useless. You cannot stare at dashboards 24/7.&lt;/p&gt;

&lt;p&gt;Set up &lt;strong&gt;alerts&lt;/strong&gt; with smart thresholds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Warning Threshold&lt;/th&gt;
&lt;th&gt;Critical Threshold&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU Usage&lt;/td&gt;
&lt;td&gt;&amp;gt; 80% for 5 min&lt;/td&gt;
&lt;td&gt;&amp;gt; 90% for 2 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory Usage&lt;/td&gt;
&lt;td&gt;&amp;gt; 85%&lt;/td&gt;
&lt;td&gt;&amp;gt; 95%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk Space&lt;/td&gt;
&lt;td&gt;&amp;lt; 25% free&lt;/td&gt;
&lt;td&gt;&amp;lt; 10% free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Rate&lt;/td&gt;
&lt;td&gt;&amp;gt; 1%&lt;/td&gt;
&lt;td&gt;&amp;gt; 5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response Time&lt;/td&gt;
&lt;td&gt;&amp;gt; 500ms avg&lt;/td&gt;
&lt;td&gt;&amp;gt; 2s avg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Do not alert on every small blip.&lt;/strong&gt; Use time windows (e.g., "CPU &amp;gt; 80% for 5 consecutive minutes") to avoid alert fatigue — a flood of noisy alerts that people start ignoring.&lt;/p&gt;

&lt;p&gt;Tools: PagerDuty, OpsGenie, Slack alerts, AWS CloudWatch Alarms, Grafana Alerts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: What Do You Do Next to Keep Things Running Smoothly?
&lt;/h2&gt;

&lt;p&gt;You detected the problem. Now what? Here are the key strategies — from automatic to manual.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Auto-Scaling: Get More Help
&lt;/h3&gt;

&lt;p&gt;If your server is overloaded, the simplest answer is: &lt;strong&gt;add more servers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Auto-scaling is when your infrastructure automatically spins up new server instances when load is high, and shuts them down when load drops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Normal traffic:   [Server 1]
Traffic spike:    [Server 1] [Server 2] [Server 3]
Traffic drops:    [Server 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works with a &lt;strong&gt;load balancer&lt;/strong&gt; sitting in front — it distributes incoming requests across all available instances so no single server gets crushed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt; = more instances (this is what auto-scaling does).&lt;br&gt;
&lt;strong&gt;Vertical scaling&lt;/strong&gt; = bigger instance (more CPU/RAM on the same machine). Harder to do automatically.&lt;/p&gt;

&lt;p&gt;Cloud providers (AWS, GCP, Azure) all have auto-scaling built in.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Circuit Breaker: Stop the Bleeding
&lt;/h3&gt;

&lt;p&gt;Imagine your server calls another service (a payment API, a database, a third-party service). That service is slow or down. Your server keeps waiting... and waiting... and all your threads are now stuck waiting for something that will never respond. Your whole server grinds to a halt because of &lt;strong&gt;someone else's problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Circuit Breaker pattern&lt;/strong&gt; prevents this.&lt;/p&gt;

&lt;p&gt;It works in three states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLOSED (Normal)
  → Requests pass through
  → Failures are counted

OPEN (Problem detected)
  → Requests immediately fail fast
  → No waiting, no timeout
  → Returns an error or fallback instantly

HALF-OPEN (Testing recovery)
  → A few test requests get through
  → If they succeed → back to CLOSED
  → If they fail → back to OPEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is called a circuit breaker because it works exactly like the electrical circuit breaker in your house — when something goes wrong, it cuts the connection to stop further damage.&lt;/p&gt;

&lt;p&gt;Libraries: &lt;code&gt;opossum&lt;/code&gt; (Node.js), &lt;code&gt;resilience4j&lt;/code&gt; (Java), &lt;code&gt;polly&lt;/code&gt; (.NET).&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Graceful Degradation: Do Less, Not Nothing
&lt;/h3&gt;

&lt;p&gt;When part of your system is broken, the goal is to &lt;strong&gt;keep the core experience working&lt;/strong&gt;, even if some features are temporarily unavailable.&lt;/p&gt;

&lt;p&gt;Real-world examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YouTube&lt;/strong&gt; goes down? Show the homepage with a "video unavailable" message instead of crashing entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation engine&lt;/strong&gt; fails? Show generic popular content instead of personalized picks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment service&lt;/strong&gt; is slow? Disable the "buy now" button and show a "try again shortly" message instead of hanging the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is better than an error page that says "500 Internal Server Error" with nothing else.&lt;/p&gt;

&lt;p&gt;The key idea: &lt;strong&gt;degrade gracefully, fail loudly only when you have no other choice.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Caching: Avoid Repeating Work
&lt;/h3&gt;

&lt;p&gt;Many server problems come from doing the same expensive work over and over. Caching stores the result of expensive operations so you can reuse them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without cache:
User → Server → Database (100ms) → User

With cache:
User → Server → Cache (1ms) → User  (if cached)
User → Server → Database (100ms) → Cache → User  (if not cached)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Types of caching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;In-memory cache:&lt;/strong&gt; Redis, Memcached — extremely fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP caching:&lt;/strong&gt; &lt;code&gt;Cache-Control&lt;/code&gt; headers tell browsers and CDNs to store responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database query caching:&lt;/strong&gt; Cache frequently run queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your server is struggling, a well-configured cache can reduce database load by 80% or more.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Rate Limiting: Control Incoming Traffic
&lt;/h3&gt;

&lt;p&gt;If traffic spikes and you cannot scale fast enough, you need to protect yourself by &lt;strong&gt;limiting how many requests any single client can make&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example: Allow 100 requests per minute per IP. After that, return &lt;code&gt;429 Too Many Requests&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This protects against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accidental infinite loops in client code&lt;/li&gt;
&lt;li&gt;DDoS (Distributed Denial of Service) attacks&lt;/li&gt;
&lt;li&gt;Scrapers hammering your API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not just about bad actors — rate limiting is also good for your own internal services to prevent one slow consumer from starving everyone else.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Retry with Exponential Backoff: Be Patient, Not Aggressive
&lt;/h3&gt;

&lt;p&gt;Sometimes a service is temporarily down and recovers in seconds. Clients should retry — but &lt;strong&gt;smart retries&lt;/strong&gt;, not aggressive ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad retry:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fail → Retry immediately → Fail → Retry immediately → Fail...
(This makes the overloaded server worse)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good retry with exponential backoff:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fail → Wait 1s → Retry
Fail → Wait 2s → Retry
Fail → Wait 4s → Retry
Fail → Wait 8s → Retry (give up after X attempts)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each retry waits twice as long as the last. Add a bit of random delay (called &lt;strong&gt;jitter&lt;/strong&gt;) so thousands of clients do not all retry at the exact same moment, which would cause another spike.&lt;/p&gt;




&lt;h3&gt;
  
  
  7. Rollbacks: Undo What Broke It
&lt;/h3&gt;

&lt;p&gt;Sometimes the issue is a bad deployment. The fastest fix is often to &lt;strong&gt;roll back&lt;/strong&gt; to the previous working version.&lt;/p&gt;

&lt;p&gt;Blue-green deployment and canary releases are strategies to reduce this risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blue-Green:&lt;/strong&gt; You have two identical environments (blue = live, green = new). Deploy to green, test it, then switch traffic. If something breaks, switch back to blue instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canary Release:&lt;/strong&gt; Roll out the new version to 5% of users first. If metrics look good, increase to 20%, then 50%, then 100%. If something breaks, only 5% of users were affected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These patterns let you catch problems early without taking down everything.&lt;/p&gt;




&lt;h3&gt;
  
  
  8. Runbooks: The Human Response Plan
&lt;/h3&gt;

&lt;p&gt;All the automation in the world cannot cover every scenario. You need a &lt;strong&gt;runbook&lt;/strong&gt; — a documented set of steps that a human follows when a specific alert fires.&lt;/p&gt;

&lt;p&gt;A good runbook answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does this alert mean?&lt;/li&gt;
&lt;li&gt;How urgent is it?&lt;/li&gt;
&lt;li&gt;What are the first three things to check?&lt;/li&gt;
&lt;li&gt;How do I escalate if I cannot fix it?&lt;/li&gt;
&lt;li&gt;What commands should I run?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example runbook entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Alert: High Memory Usage (&amp;gt; 90% for 10 minutes)
&lt;span class="p"&gt;
1.&lt;/span&gt; SSH into the affected server
&lt;span class="p"&gt;2.&lt;/span&gt; Run: &lt;span class="sb"&gt;`ps aux --sort=-%mem | head -20`&lt;/span&gt; to find the top memory consumers
&lt;span class="p"&gt;3.&lt;/span&gt; Check for memory leaks in the app logs: &lt;span class="sb"&gt;`grep "OutOfMemory" /var/log/app.log`&lt;/span&gt;
&lt;span class="p"&gt;4.&lt;/span&gt; If a rogue process is found: restart the service
&lt;span class="p"&gt;5.&lt;/span&gt; If memory does not recover: trigger a scale-out event
&lt;span class="p"&gt;6.&lt;/span&gt; Escalate to on-call engineer if unresolved after 15 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A runbook turns a stressful incident into a checklist. It is boring when things are calm and invaluable at 3am during an outage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting It All Together: The Full Answer Framework
&lt;/h2&gt;

&lt;p&gt;If an interviewer asks you this question, here is the structure of a great answer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection (Observability):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I would monitor core metrics: CPU, memory, disk, network&lt;/li&gt;
&lt;li&gt;I would track application metrics: latency, error rate, throughput&lt;/li&gt;
&lt;li&gt;I would have health check endpoints (liveness and readiness)&lt;/li&gt;
&lt;li&gt;I would use structured logging for traceability&lt;/li&gt;
&lt;li&gt;I would set up smart alerts with meaningful thresholds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response (Resilience):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-scaling to handle load spikes&lt;/li&gt;
&lt;li&gt;Circuit breakers to prevent cascading failures from downstream services&lt;/li&gt;
&lt;li&gt;Graceful degradation to keep core features working&lt;/li&gt;
&lt;li&gt;Caching to reduce repeated expensive work&lt;/li&gt;
&lt;li&gt;Rate limiting to protect against traffic floods&lt;/li&gt;
&lt;li&gt;Retry with exponential backoff for transient failures&lt;/li&gt;
&lt;li&gt;Rollback strategies (blue-green, canary) for bad deployments&lt;/li&gt;
&lt;li&gt;Runbooks so on-call engineers know exactly what to do&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-World Tools Worth Knowing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Popular Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Metrics &amp;amp; Dashboards&lt;/td&gt;
&lt;td&gt;Grafana, Datadog, Prometheus, AWS CloudWatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logging&lt;/td&gt;
&lt;td&gt;ELK Stack (Elasticsearch, Logstash, Kibana), Loki, Splunk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alerting&lt;/td&gt;
&lt;td&gt;PagerDuty, OpsGenie, Grafana Alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;APM (App Performance)&lt;/td&gt;
&lt;td&gt;Datadog APM, New Relic, Sentry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uptime Monitoring&lt;/td&gt;
&lt;td&gt;UptimeRobot, Pingdom, Checkly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circuit Breakers&lt;/td&gt;
&lt;td&gt;Resilience4j, Opossum (Node.js), Polly (.NET)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching&lt;/td&gt;
&lt;td&gt;Redis, Memcached, Varnish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load Balancing / Scaling&lt;/td&gt;
&lt;td&gt;AWS ALB + Auto Scaling, Kubernetes HPA, NGINX&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The interview question is asking you to think like a system that &lt;strong&gt;observes itself&lt;/strong&gt; and &lt;strong&gt;heals itself&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detect&lt;/strong&gt; with metrics (CPU, memory, disk, network), application signals (latency, error rate), health checks, and structured logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respond&lt;/strong&gt; with auto-scaling, circuit breakers, graceful degradation, caching, rate limiting, smart retries, rollbacks, and runbooks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best systems do not just survive failures — they are designed to &lt;strong&gt;expect them&lt;/strong&gt; and handle them without waking anyone up at 3am.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this useful? Drop a comment with the trickiest server question you have faced in an interview — I would love to hear it.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.manageengine.com/network-monitoring/blog/server-monitoring-checklist.html" rel="noopener noreferrer"&gt;The only server health monitoring checklist you need in 2025 - ManageEngine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uptimerobot.com/knowledge-hub/monitoring/ultimate-guide-to-server-monitoring-metrics-tools-and-best-practices/" rel="noopener noreferrer"&gt;Ultimate Guide to Server Monitoring - UptimeRobot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sematext.com/blog/server-monitoring-best-practices/" rel="noopener noreferrer"&gt;Server Health and Performance Monitoring Best Practices - Sematext&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/system-design/what-is-circuit-breaker-pattern-in-microservices/" rel="noopener noreferrer"&gt;Circuit Breaker Pattern in Microservices - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zuplo.com/learning-center/api-gateway-resilience-fault-tolerance" rel="noopener noreferrer"&gt;API Gateway Resilience and Fault Tolerance - Zuplo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sreschool.com/blog/graceful-degradation/" rel="noopener noreferrer"&gt;What is Graceful Degradation? - SRE School&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/system-design/microservices-resilience-patterns/" rel="noopener noreferrer"&gt;Microservices Resilience Patterns - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>beginners</category>
      <category>sre</category>
    </item>
    <item>
      <title>How to Remove a File from Git History (And What to Watch Out For)</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Wed, 22 Apr 2026 15:10:32 +0000</pubDate>
      <link>https://dev.to/edriso/how-to-remove-a-file-from-git-history-and-what-to-watch-out-for-1o15</link>
      <guid>https://dev.to/edriso/how-to-remove-a-file-from-git-history-and-what-to-watch-out-for-1o15</guid>
      <description>&lt;p&gt;It happens to everyone. You commit a file you shouldn't have — maybe a &lt;code&gt;.env&lt;/code&gt; with API keys, a huge binary, or just something private — and then you push it.&lt;/p&gt;

&lt;p&gt;The bad news: deleting the file and committing again doesn't actually remove it from git history. Anyone can still go back and see it.&lt;/p&gt;

&lt;p&gt;The good news: you can rewrite history to remove it completely. Here's how.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why deleting the file isn't enough
&lt;/h2&gt;

&lt;p&gt;Git keeps a full snapshot of every commit. Even after you delete a file, it still lives in older commits. Someone can always run &lt;code&gt;git log -- filename&lt;/code&gt; or check out an old commit to get it back.&lt;/p&gt;

&lt;p&gt;To truly remove it, you need to rewrite every commit that ever touched that file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Make sure the file is deleted locally
&lt;/h2&gt;

&lt;p&gt;If the file still exists on disk, delete it first. Then stage the deletion:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;rm &lt;/span&gt;the-file.txt
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Remove the-file.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you already deleted it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Remove the-file.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2 — Rewrite git history
&lt;/h2&gt;

&lt;p&gt;This is the actual scrubbing step. Run this command (replace &lt;code&gt;the-file.txt&lt;/code&gt; with your file path):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;FILTER_BRANCH_SQUELCH_WARNING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 git filter-branch &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--index-filter&lt;/span&gt; &lt;span class="s2"&gt;"git rm --cached --ignore-unmatch the-file.txt"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--prune-empty&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tag-name-filter&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each flag does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--index-filter&lt;/code&gt; — runs a command on every commit's index (faster than checking out files)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git rm --cached --ignore-unmatch&lt;/code&gt; — removes the file from the index, silently skips commits that don't have it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--prune-empty&lt;/code&gt; — removes any commits that become empty after the file is gone&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--tag-name-filter cat&lt;/code&gt; — rewrites tags to point to the new commits&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-- --all&lt;/code&gt; — applies to all branches and refs&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Git will warn you about &lt;code&gt;filter-branch&lt;/code&gt; being error-prone and recommend &lt;code&gt;git-filter-repo&lt;/code&gt; instead. If you can install it (&lt;code&gt;pip install git-filter-repo&lt;/code&gt;), it's faster and safer. The equivalent command is just:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git filter-repo &lt;span class="nt"&gt;--path&lt;/span&gt; the-file.txt &lt;span class="nt"&gt;--invert-paths&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Clean up local dangling objects
&lt;/h2&gt;

&lt;p&gt;After rewriting, old commits still hang around in your local reflog. Clean them up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog expire &lt;span class="nt"&gt;--expire&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;now &lt;span class="nt"&gt;--all&lt;/span&gt;
git gc &lt;span class="nt"&gt;--prune&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;now &lt;span class="nt"&gt;--aggressive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4 — Force push
&lt;/h2&gt;

&lt;p&gt;This is the step that overwrites the remote history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin main &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Cautions — read before you do this
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This is a destructive, irreversible operation.&lt;/strong&gt; Once you force push rewritten history, the old commits are gone from the remote. Here's what that means in practice:&lt;/p&gt;

&lt;h3&gt;
  
  
  If others have cloned the repo
&lt;/h3&gt;

&lt;p&gt;Anyone who cloned or pulled before your rewrite will have the old history. They'll need to re-clone or do a hard reset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Their local branches with the old history will conflict with the new remote. Coordinate with your team before doing this.&lt;/p&gt;

&lt;h3&gt;
  
  
  The secret may already be compromised
&lt;/h3&gt;

&lt;p&gt;If you pushed API keys or credentials, &lt;strong&gt;assume they are already leaked&lt;/strong&gt;. Bots scan GitHub in real time. Rewriting history is cleanup — but your first step should be revoking and rotating the credentials immediately, before anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  It doesn't work on forks
&lt;/h3&gt;

&lt;p&gt;If someone forked your repo before the rewrite, they still have the old history. You can't rewrite their copy.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub/GitLab may cache the old commits
&lt;/h3&gt;

&lt;p&gt;GitHub keeps cached views of old commits for a short time even after a force push. You can contact GitHub support to purge the cache, but for leaked secrets, rotate first — don't wait.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Delete the file&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git rm the-file.txt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rewrite history&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;git filter-branch ...&lt;/code&gt; or &lt;code&gt;git filter-repo&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clean up local objects&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;git reflog expire&lt;/code&gt; + &lt;code&gt;git gc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Force push&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git push origin main --force&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Best practices to avoid this in the first place
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add sensitive files to &lt;code&gt;.gitignore&lt;/code&gt; &lt;strong&gt;before&lt;/strong&gt; you create them&lt;/li&gt;
&lt;li&gt;Use a &lt;code&gt;.env.example&lt;/code&gt; file with dummy values instead of committing real secrets&lt;/li&gt;
&lt;li&gt;Tools like &lt;a href="https://github.com/awslabs/git-secrets" rel="noopener noreferrer"&gt;git-secrets&lt;/a&gt; or &lt;a href="https://github.com/gitleaks/gitleaks" rel="noopener noreferrer"&gt;gitleaks&lt;/a&gt; can scan commits before they're pushed and block accidental leaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rewriting history is a useful escape hatch — but the best commit to regret is the one you never made.&lt;/p&gt;

</description>
      <category>git</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>JavaScript Promises — Understand what a Promise actually is, how .then() chaining works under the hood, and how async/await connects to all of it</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Wed, 22 Apr 2026 15:03:52 +0000</pubDate>
      <link>https://dev.to/edriso/javascript-promises-understand-what-a-promise-actually-is-how-then-chaining-works-under-the-1dfm</link>
      <guid>https://dev.to/edriso/javascript-promises-understand-what-a-promise-actually-is-how-then-chaining-works-under-the-1dfm</guid>
      <description>&lt;p&gt;One question that comes up a lot when learning JavaScript async code is this: when you &lt;code&gt;return&lt;/code&gt; a value inside &lt;code&gt;.then()&lt;/code&gt;, does it get wrapped in &lt;code&gt;Promise.resolve(value)&lt;/code&gt; automatically? And if you &lt;code&gt;throw&lt;/code&gt; something, does it become &lt;code&gt;Promise.reject(error)&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Short answer: &lt;strong&gt;yes, exactly right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's one of those things that sounds small but really clicks everything into place once you get it. Let me break it all down.&lt;/p&gt;




&lt;h2&gt;
  
  
  What even is a Promise?
&lt;/h2&gt;

&lt;p&gt;Before ES6 (back when callbacks ruled everything), async code looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getUserFromDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;getPostsByUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// imagine this going 5 levels deep...&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;This is called &lt;strong&gt;callback hell&lt;/strong&gt; — and it's as bad as it sounds.&lt;/p&gt;

&lt;p&gt;A Promise is a cleaner way to handle async operations. Think of it like ordering food at a restaurant. You place your order (start the async operation), and instead of standing at the kitchen window waiting, the waiter gives you a &lt;strong&gt;number&lt;/strong&gt; (the Promise). You go sit down and do other things. When the food is ready, they call your number.&lt;/p&gt;

&lt;p&gt;A Promise is in one of three states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pending&lt;/strong&gt; — still waiting (the kitchen is still cooking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled&lt;/strong&gt; — success, you have a value (food arrived)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt; — something went wrong (they're out of your order)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The &lt;code&gt;.then()&lt;/code&gt; chaining trick
&lt;/h2&gt;

&lt;p&gt;Here's the interesting part. When you chain &lt;code&gt;.then()&lt;/code&gt; calls, each &lt;code&gt;.then()&lt;/code&gt; returns a &lt;strong&gt;new Promise&lt;/strong&gt;. And what that Promise resolves or rejects with depends on what happens inside the callback.&lt;/p&gt;

&lt;p&gt;The rules are simple:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you do inside &lt;code&gt;.then()&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;What the next Promise gets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;return someValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wraps it: &lt;code&gt;Promise.resolve(someValue)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;return anotherPromise&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Waits for that promise and uses its result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;throw new Error(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wraps it: &lt;code&gt;Promise.reject(error)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// becomes Promise.resolve("John")&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "John"&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oops!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// becomes Promise.reject(Error("Oops!"))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This won't run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Oops!"&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This chaining is powerful because you avoid nesting — each &lt;code&gt;.then()&lt;/code&gt; hands off to the next one cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  async/await is just Promises in disguise
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;async/await&lt;/code&gt; isn't a different system — it's syntax sugar on top of Promises. The same rules apply.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// same as: return Promise.resolve("John")&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something broke&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// same as: return Promise.reject(...)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;await&lt;/code&gt; just pauses execution until the Promise settles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// waits for Promise to resolve&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// catches rejections&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 &lt;code&gt;try/catch&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt; is equivalent to &lt;code&gt;.then().catch()&lt;/code&gt; — same idea, cleaner look.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real use case: Fetching data from an API
&lt;/h2&gt;

&lt;p&gt;Here's a practical example — fetching a GitHub user's profile and then their repos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// With .then() chaining&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getGithubInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;           &lt;span class="c1"&gt;// parse JSON (returns a Promise)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/repos`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;repos&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Repos:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Same thing with async/await — cleaner!&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getGithubInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reposResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.github.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/repos`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;reposResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Repos:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&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;Both do the same thing. Most people prefer &lt;code&gt;async/await&lt;/code&gt; because it reads like regular synchronous code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Promise represents a future value from an async operation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.then()&lt;/code&gt; always returns a new Promise — whatever you &lt;code&gt;return&lt;/code&gt; becomes &lt;code&gt;Promise.resolve(...)&lt;/code&gt;, whatever you &lt;code&gt;throw&lt;/code&gt; becomes &lt;code&gt;Promise.reject(...)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;async/await&lt;/code&gt; is built on top of Promises — they are the same thing underneath&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;.catch()&lt;/code&gt; or &lt;code&gt;try/catch&lt;/code&gt; to handle errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Promises still feel fuzzy, that's okay. The best way to solidify this is to build something — try fetching data from a public API, chain a few &lt;code&gt;.then()&lt;/code&gt; calls, and break things on purpose to see what happens.&lt;/p&gt;

&lt;p&gt;You'll get it. It just takes repetition.&lt;/p&gt;




&lt;p&gt;Keep asking questions — they help everyone learn.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Dim Other Cards on Hover with Pure CSS</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Mon, 20 Apr 2026 15:40:11 +0000</pubDate>
      <link>https://dev.to/edriso/dim-other-cards-on-hover-with-pure-css-35p8</link>
      <guid>https://dev.to/edriso/dim-other-cards-on-hover-with-pure-css-35p8</guid>
      <description>&lt;p&gt;You've probably seen this effect before — you hover over one card, and all the other cards fade out a little, making the hovered one stand out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before hover:             While hovering card B:

┌──────┐ ┌──────┐ ┌──────┐     ┌──────┐ ┌──────┐ ┌──────┐
│  A   │ │  B   │ │  C   │     │  A   │ │  B   │ │  C   │
└──────┘ └──────┘ └──────┘     └──────┘ └──────┘ └──────┘
 100%     100%     100%          dim      bright    dim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's clean, it draws attention to the right place, and it takes about 5 lines of CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTML
&lt;/h2&gt;

&lt;p&gt;Nothing special here — a wrapper div and some cards inside it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cards"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card A&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card B&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card C&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The CSS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.cards&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&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;That's it. Let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.cards:has(.card:hover)&lt;/code&gt; — targets the wrapper &lt;strong&gt;when any card inside it is being hovered&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.card:not(:hover)&lt;/code&gt; — selects all cards &lt;strong&gt;except&lt;/strong&gt; the one being hovered&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;opacity: 0.5&lt;/code&gt; — dims them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So in plain English: &lt;em&gt;"If something inside &lt;code&gt;.cards&lt;/code&gt; is hovered, dim every &lt;code&gt;.card&lt;/code&gt; that isn't the hovered one."&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a smooth transition
&lt;/h2&gt;

&lt;p&gt;The snap between full and dimmed opacity can feel abrupt. Add a transition to the cards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.cards&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&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;Now it fades in and out smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Works across columns too
&lt;/h2&gt;

&lt;p&gt;This approach works even when your cards are split across multiple columns (like a masonry layout), because the selector targets by class anywhere inside the wrapper — not just direct children.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cards"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card A&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card C&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card B&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Card D&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same CSS still works — hover card A, and B, C, D all dim regardless of which column they're in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser support
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;:has()&lt;/code&gt; selector is supported in all modern browsers. Just keep in mind it doesn't work in Firefox versions before 121 or older browsers, so add a graceful fallback if you need wide coverage (e.g. just skip the effect entirely for those browsers — it's purely visual).&lt;/p&gt;




&lt;p&gt;Simple, no JavaScript, no extra libraries. Just CSS doing what it's good at.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Built a Web App to Burn Bad Memories and Grow From Them</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Thu, 09 Apr 2026 20:15:00 +0000</pubDate>
      <link>https://dev.to/edriso/i-built-a-web-app-to-burn-bad-memories-and-grow-from-them-56fj</link>
      <guid>https://dev.to/edriso/i-built-a-web-app-to-burn-bad-memories-and-grow-from-them-56fj</guid>
      <description>&lt;p&gt;We all carry memories that weigh us down. Things we said, things we didn't say, moments we wish went differently.&lt;/p&gt;

&lt;p&gt;I built a small web app called &lt;strong&gt;Grow &amp;amp; Let Go&lt;/strong&gt; — a quiet space to write down a painful memory, find the lesson in it, and let it go.&lt;/p&gt;

&lt;p&gt;You write it. You watch it burn. You see your lesson grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when you submit
&lt;/h2&gt;

&lt;p&gt;The burning isn't just a simple fade-out. There's a canvas-based fire particle system with embers rising, smoke drifting, and ash scattering. The card chars and crumbles as it burns.&lt;/p&gt;

&lt;p&gt;And when the fire clears, a plant sprouts from the ground — the stem draws upward, leaves unfurl, a flower blooms. Fireflies appear. The whole mood shifts from warmth to calm.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/WXYwGIRznK4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTML, CSS, vanilla JS&lt;/strong&gt; — no frameworks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;anime.js&lt;/strong&gt; for orchestrating animation timelines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canvas API&lt;/strong&gt; for the fire particle system with additive blending&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SVG stroke animation&lt;/strong&gt; for the plant growth (stroke-dashoffset drawing the stem upward)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS mix-blend-mode and blur&lt;/strong&gt; for smoke effects&lt;/li&gt;
&lt;li&gt;Ambient floating particles and fireflies for atmosphere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing runs in the browser. No backend, no accounts, no data stored anywhere.&lt;/p&gt;

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

&lt;p&gt;🌱 &lt;a href="https://edriso.github.io/grow-and-let-go/" rel="noopener noreferrer"&gt;Live App&lt;/a&gt;&lt;br&gt;
💻 &lt;a href="https://github.com/edriso/grow-and-let-go" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And if that memory was a mistake toward someone still in your life, and you never apologized... here's another app for that:&lt;/p&gt;

&lt;p&gt;💌 &lt;a href="https://github.com/edriso/i-forgot-to-say-sorry" rel="noopener noreferrer"&gt;I Forgot to Say Sorry&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>🧠 The Backend Developer Fundamentals Guide</title>
      <dc:creator>Mohamed Idris</dc:creator>
      <pubDate>Wed, 08 Apr 2026 11:22:54 +0000</pubDate>
      <link>https://dev.to/edriso/the-backend-developer-fundamentals-guide-3j55</link>
      <guid>https://dev.to/edriso/the-backend-developer-fundamentals-guide-3j55</guid>
      <description>&lt;h3&gt;
  
  
  &lt;em&gt;Understand the engine before you drive the car.&lt;/em&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This guide teaches you the &lt;strong&gt;concepts behind every framework&lt;/strong&gt;. Learn this once, and Spring, Node, Laravel, Django — they'll all just be different flavors of the same thing.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How The Internet Actually Works&lt;/li&gt;
&lt;li&gt;Request &amp;amp; Response — The Heart of Everything&lt;/li&gt;
&lt;li&gt;What a Server Actually Does&lt;/li&gt;
&lt;li&gt;How Data Flows Through a System&lt;/li&gt;
&lt;li&gt;Memory, Threads &amp;amp; Processes&lt;/li&gt;
&lt;li&gt;Databases — Where Data Lives&lt;/li&gt;
&lt;li&gt;APIs — How Systems Talk to Each Other&lt;/li&gt;
&lt;li&gt;Authentication &amp;amp; Authorization&lt;/li&gt;
&lt;li&gt;Caching — Making Things Fast&lt;/li&gt;
&lt;li&gt;Security Basics&lt;/li&gt;
&lt;li&gt;Architecture Patterns&lt;/li&gt;
&lt;li&gt;Networking Essentials&lt;/li&gt;
&lt;li&gt;Linux &amp;amp; The Command Line&lt;/li&gt;
&lt;li&gt;Version Control (Git)&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;DevOps Basics&lt;/li&gt;
&lt;li&gt;The Learning Order (Roadmap)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. How The Internet Actually Works
&lt;/h2&gt;

&lt;p&gt;Before you write a single line of backend code, you need to understand how the internet works. It's simpler than you think.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS — The Phone Book of the Internet
&lt;/h3&gt;

&lt;p&gt;When you type &lt;code&gt;google.com&lt;/code&gt; in your browser, your computer doesn't know what that means. Computers only understand numbers (IP addresses like &lt;code&gt;142.250.80.46&lt;/code&gt;). So your computer asks a &lt;strong&gt;DNS server&lt;/strong&gt; (Domain Name System): "Hey, what's the IP address for google.com?"&lt;/p&gt;

&lt;p&gt;Think of it like this: you know your friend's name, but you need their phone number to call them. DNS is the contact list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The flow:&lt;/strong&gt;&lt;br&gt;
You type &lt;code&gt;google.com&lt;/code&gt; → Your computer asks DNS → DNS says "that's &lt;code&gt;142.250.80.46&lt;/code&gt;" → Your computer connects to that IP address.&lt;/p&gt;
&lt;h3&gt;
  
  
  TCP/IP — The Delivery System
&lt;/h3&gt;

&lt;p&gt;Once your computer knows the IP address, it needs to send and receive data. That's where TCP/IP comes in.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IP (Internet Protocol):&lt;/strong&gt; This is like the address on a package. It tells data where to go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TCP (Transmission Control Protocol):&lt;/strong&gt; This makes sure the data arrives completely and in order. It's like a delivery service that makes you sign for the package — it confirms everything arrived.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters for backend:&lt;/strong&gt; Every single thing your server does involves TCP/IP. When a user opens your app, their phone creates a TCP connection to your server. Understanding this helps you debug network issues later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ports — Doors Into Your Server
&lt;/h3&gt;

&lt;p&gt;Your server is like a building, and &lt;strong&gt;ports&lt;/strong&gt; are the doors. Different services use different doors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Port &lt;strong&gt;80&lt;/strong&gt; → Regular web traffic (HTTP)&lt;/li&gt;
&lt;li&gt;Port &lt;strong&gt;443&lt;/strong&gt; → Secure web traffic (HTTPS)&lt;/li&gt;
&lt;li&gt;Port &lt;strong&gt;5432&lt;/strong&gt; → PostgreSQL database&lt;/li&gt;
&lt;li&gt;Port &lt;strong&gt;3306&lt;/strong&gt; → MySQL database&lt;/li&gt;
&lt;li&gt;Port &lt;strong&gt;27017&lt;/strong&gt; → MongoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When someone visits your website, they're knocking on port 80 or 443 of your server.&lt;/p&gt;
&lt;h3&gt;
  
  
  HTTP/HTTPS — The Language of the Web
&lt;/h3&gt;

&lt;p&gt;HTTP (HyperText Transfer Protocol) is the language browsers and servers speak. HTTPS is the same thing but encrypted (the "S" stands for Secure).&lt;/p&gt;

&lt;p&gt;Every time you load a webpage, your browser sends an HTTP &lt;strong&gt;request&lt;/strong&gt;, and the server sends back an HTTP &lt;strong&gt;response&lt;/strong&gt;. That's literally all web development is at its core — requests and responses.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Request &amp;amp; Response — The Heart of Everything
&lt;/h2&gt;

&lt;p&gt;This is the &lt;strong&gt;single most important concept&lt;/strong&gt; in backend development. Everything else is built on top of this.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a Request?
&lt;/h3&gt;

&lt;p&gt;A request is a message from a client (browser, mobile app, another server) asking your server to do something. Every request has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Method (Verb):&lt;/strong&gt; What action do you want?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt; → "Give me some data" (like loading a page)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST&lt;/code&gt; → "Here's some new data, save it" (like submitting a form)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT&lt;/code&gt; → "Update this existing data completely"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PATCH&lt;/code&gt; → "Update just part of this data"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt; → "Remove this data"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;URL (Path):&lt;/strong&gt; What resource do you want?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/users&lt;/code&gt; → the users resource&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/users/42&lt;/code&gt; → user number 42 specifically&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/users/42/orders&lt;/code&gt; → orders belonging to user 42&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; Extra info about the request (like metadata)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Content-Type: application/json&lt;/code&gt; → "I'm sending JSON data"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Authorization: Bearer abc123&lt;/code&gt; → "Here's my login token"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Accept: application/json&lt;/code&gt; → "Please respond with JSON"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Body:&lt;/strong&gt; The actual data (only for POST, PUT, PATCH)&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ahmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ahmed@example.com"&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;h3&gt;
  
  
  What is a Response?
&lt;/h3&gt;

&lt;p&gt;The response is your server's answer. Every response has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Status Code:&lt;/strong&gt; A number that tells the client what happened&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;200&lt;/code&gt; → "OK, here's what you asked for"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;201&lt;/code&gt; → "Created — I made the new thing you wanted"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;400&lt;/code&gt; → "Bad Request — you sent me something wrong"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;401&lt;/code&gt; → "Unauthorized — who are you? Log in first"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;403&lt;/code&gt; → "Forbidden — I know who you are, but you can't do this"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;404&lt;/code&gt; → "Not Found — that thing doesn't exist"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;500&lt;/code&gt; → "Internal Server Error — I broke, it's my fault"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Headers:&lt;/strong&gt; Extra info about the response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Body:&lt;/strong&gt; The actual data being sent back&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;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="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ahmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ahmed@example.com"&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;h3&gt;
  
  
  The Full Picture
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks "Sign Up" button
        ↓
Browser sends POST request to /api/users
  with body: { name: "Ahmed", email: "ahmed@example.com", password: "..." }
        ↓
Server receives the request
        ↓
Server validates the data (is the email real? is the password strong enough?)
        ↓
Server hashes the password (never store plain passwords!)
        ↓
Server saves the user to the database
        ↓
Server sends back a response: 201 Created
  with body: { id: 42, name: "Ahmed", message: "Account created!" }
        ↓
Browser shows "Welcome, Ahmed!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;This flow is identical in every framework.&lt;/strong&gt; Express, Spring, Django, Laravel — they all do this exact thing. The only difference is the syntax.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. What a Server Actually Does
&lt;/h2&gt;

&lt;p&gt;A server is just a computer that's always on, always connected to the internet, and always listening for requests.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Server's Job, Step by Step
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Listen&lt;/strong&gt; — The server sits and waits on a specific port (usually 80 or 443), doing nothing until someone sends a request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Receive&lt;/strong&gt; — A request arrives. The server reads the method, URL, headers, and body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route&lt;/strong&gt; — The server figures out which piece of code should handle this request. "Oh, they want &lt;code&gt;GET /users/42&lt;/code&gt;? Let me call the &lt;code&gt;getUserById&lt;/code&gt; function."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process&lt;/strong&gt; — The actual business logic happens here: validate data, talk to the database, calculate things, call other services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respond&lt;/strong&gt; — The server builds a response with a status code and data, then sends it back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go back to step 1&lt;/strong&gt; — The server goes back to listening for the next request.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Middleware — The Assembly Line
&lt;/h3&gt;

&lt;p&gt;In most frameworks, before your request reaches the actual handler, it passes through a chain of &lt;strong&gt;middleware&lt;/strong&gt;. Think of it like a factory assembly line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request arrives
    ↓
[Logging Middleware] — "Let me record that this request happened"
    ↓
[Auth Middleware] — "Let me check if this user is logged in"
    ↓
[Validation Middleware] — "Let me check if the data is correct"
    ↓
[Your Actual Handler] — "OK, now I'll do the real work"
    ↓
Response goes back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every framework has middleware. Express calls it middleware. Django calls it middleware. Spring calls it filters/interceptors. Laravel calls it middleware. Same concept, different names.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. How Data Flows Through a System
&lt;/h2&gt;

&lt;p&gt;When you build a real app, data moves through multiple layers. Understanding this flow is what separates someone who just copies code from someone who actually understands what's happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Typical Layers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLIENT (Browser/App)
    ↕ HTTP Request/Response
CONTROLLER / ROUTE HANDLER
    → Receives the request, extracts data from it
    → Calls the right service
    ↕
SERVICE / BUSINESS LOGIC
    → The "brain" — decides what to do
    → Applies rules: "Users under 18 can't buy this"
    → Coordinates between different pieces
    ↕
REPOSITORY / DATA ACCESS
    → Talks to the database
    → Translates between your code's objects and database rows
    ↕
DATABASE
    → Stores data permanently
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Layers Matter
&lt;/h3&gt;

&lt;p&gt;Imagine you're building a food delivery app. A user places an order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Controller&lt;/strong&gt; receives: &lt;code&gt;POST /orders&lt;/code&gt; with &lt;code&gt;{ restaurantId: 5, items: [...] }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt; checks: Is the restaurant open? Does the user have enough balance? Is there a driver available?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository&lt;/strong&gt; saves the order to the database, updates the user's balance, notifies the restaurant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response&lt;/strong&gt; goes back: &lt;code&gt;201 Created&lt;/code&gt; with the order details&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you dump all of this into one file, it becomes an unreadable mess. Layers keep things organized and reusable. Every professional codebase uses layers, regardless of the framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Memory, Threads &amp;amp; Processes
&lt;/h2&gt;

&lt;p&gt;This is where most tutorials skip and where most junior devs get confused. But it's essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory — Your Program's Workspace
&lt;/h3&gt;

&lt;p&gt;When your server starts, the operating system gives it a chunk of &lt;strong&gt;RAM&lt;/strong&gt; (memory). Think of RAM like a desk — it's where your program puts things it's currently working with.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stack Memory:&lt;/strong&gt; Fast, organized, automatic. Used for simple variables and function calls. When a function finishes, its stack memory is automatically cleaned up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heap Memory:&lt;/strong&gt; Bigger, messier, manual (or garbage-collected). Used for objects, arrays, and anything complex. Stays around until your code (or the garbage collector) removes it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; If your server creates tons of objects and never cleans them up, you get a &lt;strong&gt;memory leak&lt;/strong&gt;. Your server slowly uses more and more RAM until it crashes. This is a real-world problem you'll face.&lt;/p&gt;

&lt;h3&gt;
  
  
  Processes — Independent Workers
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;process&lt;/strong&gt; is a running program. When you start your server, that's one process. Each process gets its own memory — processes don't share memory with each other.&lt;/p&gt;

&lt;p&gt;If your server crashes, the process dies. That's why in production we use tools that automatically restart crashed processes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Threads — Workers Inside a Worker
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;thread&lt;/strong&gt; is like a worker inside a process. One process can have multiple threads, and they all share the same memory.&lt;/p&gt;

&lt;p&gt;Think of a restaurant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;process&lt;/strong&gt; is the restaurant itself&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;threads&lt;/strong&gt; are the waiters&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;memory&lt;/strong&gt; is the kitchen and the order board&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Multiple waiters (threads) can serve different tables (requests) at the same time, and they all share the same kitchen (memory).&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking vs Non-Blocking
&lt;/h3&gt;

&lt;p&gt;This is a critical concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Blocking:&lt;/strong&gt; When your code does something slow (like reading a file or querying a database) and the thread just sits and waits. Nothing else can happen on that thread until it's done. Like a waiter standing at the kitchen window waiting for one dish instead of taking other orders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Non-Blocking (Async):&lt;/strong&gt; The thread says "I'll come back for this later" and goes to handle other requests. When the slow operation finishes, it picks up where it left off. Like a waiter who takes another table's order while the kitchen cooks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt; is single-threaded but non-blocking (one waiter who never stops moving). &lt;strong&gt;Java/Spring&lt;/strong&gt; is multi-threaded (multiple waiters, each can wait). Both approaches work; they have different tradeoffs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency vs Parallelism
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency:&lt;/strong&gt; Handling multiple tasks by switching between them quickly (one CPU core, many tasks). Like one person cooking three dishes by switching between them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallelism:&lt;/strong&gt; Actually doing multiple tasks at the exact same time (multiple CPU cores). Like three people each cooking one dish.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need to master this immediately, but keep it in mind — as your app grows, these concepts will determine if your server can handle 100 users or 100,000.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Databases — Where Data Lives
&lt;/h2&gt;

&lt;p&gt;Memory is temporary — when your server restarts, everything in RAM is gone. Databases store data &lt;strong&gt;permanently&lt;/strong&gt; (on disk).&lt;/p&gt;

&lt;h3&gt;
  
  
  Relational Databases (SQL)
&lt;/h3&gt;

&lt;p&gt;These store data in &lt;strong&gt;tables&lt;/strong&gt; (like spreadsheets). Examples: PostgreSQL, MySQL, SQLite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;USERS TABLE:
| id | name   | email              | created_at |
|----|--------|--------------------|------------|
| 1  | Ahmed  | ahmed@example.com  | 2025-01-15 |
| 2  | Sara   | sara@example.com   | 2025-02-20 |

ORDERS TABLE:
| id | user_id | product     | amount |
|----|---------|-------------|--------|
| 1  | 1       | Laptop      | 999    |
| 2  | 1       | Mouse       | 25     |
| 3  | 2       | Keyboard    | 75     |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;user_id&lt;/code&gt; in ORDERS &lt;strong&gt;relates&lt;/strong&gt; to the &lt;code&gt;id&lt;/code&gt; in USERS. That's why they're called "relational." You can ask: "Give me all orders for user Ahmed" by joining the tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQL (Structured Query Language)&lt;/strong&gt; is how you talk to these databases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Get all users&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Get a specific user&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Add a new user&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ali'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ali@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Update a user&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Ahmed Ali'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Delete a user&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Get all orders for a user (JOIN)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Learn SQL. It's not optional.&lt;/strong&gt; Every backend framework uses SQL under the hood, even when they hide it behind an ORM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key SQL Concepts You Must Know
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary Key:&lt;/strong&gt; The unique ID for each row (usually &lt;code&gt;id&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foreign Key:&lt;/strong&gt; A column that references another table's primary key (like &lt;code&gt;user_id&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index:&lt;/strong&gt; A shortcut that makes searching faster. Like a book's index — instead of reading every page, you jump straight to the right one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transactions:&lt;/strong&gt; A way to group multiple operations. Either ALL of them succeed, or NONE of them do. Think of transferring money: subtract from account A AND add to account B. You can't do just one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization:&lt;/strong&gt; Organizing data to avoid repetition. Instead of writing "Ahmed, &lt;a href="mailto:ahmed@email.com"&gt;ahmed@email.com&lt;/a&gt;" on every order, you just reference user_id = 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrations:&lt;/strong&gt; Version control for your database structure. When you need to add a new column, you write a migration file. This way, everyone on the team can update their database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  NoSQL Databases
&lt;/h3&gt;

&lt;p&gt;These don't use tables. Instead, they use different structures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Document DBs (MongoDB):&lt;/strong&gt; Store data as JSON-like documents. Good for flexible or nested data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;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;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ahmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ahmed@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"orders"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Laptop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;999&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mouse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&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;span class="p"&gt;]&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key-Value (Redis):&lt;/strong&gt; Super simple. A key and a value. Blazing fast. Used for caching.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"session:user42"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{ loggedIn: true, name: 'Ahmed' }"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When to use what?&lt;/strong&gt; Start with PostgreSQL. It handles 95% of use cases. Use Redis for caching. Use MongoDB only if your data truly doesn't fit into tables. Don't overcomplicate your first projects.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. APIs — How Systems Talk to Each Other
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;API&lt;/strong&gt; (Application Programming Interface) is a set of rules that lets different software talk to each other. Your backend's main job is to expose an API that frontends (or other services) can use.&lt;/p&gt;

&lt;h3&gt;
  
  
  REST — The Most Common API Style
&lt;/h3&gt;

&lt;p&gt;REST isn't a technology — it's a set of conventions for designing APIs using HTTP:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List all users&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/api/users&lt;/td&gt;
&lt;td&gt;Returns an array of users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Get one user&lt;/td&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/api/users/42&lt;/td&gt;
&lt;td&gt;Returns user with id 42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create a user&lt;/td&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/api/users&lt;/td&gt;
&lt;td&gt;Creates a new user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update a user&lt;/td&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;/api/users/42&lt;/td&gt;
&lt;td&gt;Replaces user 42's data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete a user&lt;/td&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/api/users/42&lt;/td&gt;
&lt;td&gt;Removes user 42&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;REST is just a pattern. It works the same in Express, Django, Spring, Laravel — everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON — The Universal Data Format
&lt;/h3&gt;

&lt;p&gt;JSON (JavaScript Object Notation) is how APIs send data. Even non-JavaScript APIs use it:&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="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ahmed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isActive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"developer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"student"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alexandria"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Egypt"&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;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;h3&gt;
  
  
  API Design Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;nouns&lt;/strong&gt; for URLs, not verbs: &lt;code&gt;/users&lt;/code&gt; not &lt;code&gt;/getUsers&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;plural&lt;/strong&gt; names: &lt;code&gt;/users&lt;/code&gt; not &lt;code&gt;/user&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;HTTP methods&lt;/strong&gt; for actions (GET, POST, etc.) instead of putting the action in the URL&lt;/li&gt;
&lt;li&gt;Return &lt;strong&gt;proper status codes&lt;/strong&gt;: don't return &lt;code&gt;200 OK&lt;/code&gt; when something failed&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;pagination&lt;/strong&gt; for lists: &lt;code&gt;/users?page=2&amp;amp;limit=20&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Be &lt;strong&gt;consistent&lt;/strong&gt;: if one endpoint uses camelCase, all should&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GraphQL — The Alternative
&lt;/h3&gt;

&lt;p&gt;REST makes you hit multiple endpoints to get related data. GraphQL lets you ask for exactly what you want in one request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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;span class="n"&gt;user&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;orders&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;span class="n"&gt;product&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;amount&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;span class="p"&gt;}&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;Learn REST first. It's the standard. GraphQL is nice to know later.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Authentication &amp;amp; Authorization
&lt;/h2&gt;

&lt;p&gt;These are two different things and mixing them up is a classic mistake.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication (AuthN):&lt;/strong&gt; "Who are you?" → Proving your identity (logging in)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization (AuthZ):&lt;/strong&gt; "What are you allowed to do?" → Checking permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Login Works (The Real Flow)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User sends POST /login with { email, password }
2. Server finds the user in the database
3. Server checks: does the hashed password match?
4. If yes → Server creates a TOKEN (a signed string)
5. Server sends the token back to the client
6. Client stores the token (usually in memory or a cookie)
7. On every future request, client sends the token in the Authorization header
8. Server reads the token, verifies it's valid and not expired
9. Server now knows who this user is
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Passwords — Never Store Plain Text
&lt;/h3&gt;

&lt;p&gt;When a user creates a password, you &lt;strong&gt;hash&lt;/strong&gt; it (turn it into a scrambled string that can't be reversed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Password: "mypassword123"
Hashed:   "$2b$10$N9qo8uLOickgx2ZMRZoMye..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When they log in, you hash what they typed and compare it to the stored hash. You never know their actual password. This means if your database gets stolen, the attacker can't read passwords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use bcrypt or argon2.&lt;/strong&gt; Every language has a library for this.&lt;/p&gt;

&lt;h3&gt;
  
  
  JWT (JSON Web Tokens)
&lt;/h3&gt;

&lt;p&gt;A JWT is a token that contains information about the user, signed with a secret key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header.Payload.Signature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload might be: &lt;code&gt;{ userId: 42, role: "admin", exp: 1234567890 }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The server can verify this token without checking the database every time. The signature proves it wasn't tampered with.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sessions vs Tokens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sessions:&lt;/strong&gt; Server stores login state in memory or a database. The client gets a session ID cookie. Server-side state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokens (JWT):&lt;/strong&gt; Client holds the token. Server is stateless — it just verifies the signature. No server-side state needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are valid. Tokens are more popular for APIs; sessions are more traditional for web apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAuth 2.0 — "Login with Google/GitHub"
&lt;/h3&gt;

&lt;p&gt;OAuth lets users log into your app using their Google/GitHub/etc. account. You don't handle their password at all. The basic flow: your app redirects to Google → user logs in there → Google sends a code back to your app → your app exchanges that code for user info.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Caching — Making Things Fast
&lt;/h2&gt;

&lt;p&gt;Caching means storing frequently used data in a fast place so you don't have to recalculate or re-fetch it every time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Caching Happens
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser Cache:&lt;/strong&gt; The browser stores static files (images, CSS, JS) so it doesn't download them again.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN Cache:&lt;/strong&gt; A Content Delivery Network stores your files on servers worldwide, so a user in Egypt gets served from a nearby server instead of one in the US.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Cache (Redis/Memcached):&lt;/strong&gt; Your server stores frequently accessed data in memory. Way faster than hitting the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Cache:&lt;/strong&gt; The database itself caches frequent queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: Why Caching Matters
&lt;/h3&gt;

&lt;p&gt;Without cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User requests GET /popular-products
→ Server runs a complex database query (200ms)
→ This happens for EVERY user, EVERY time
→ 1000 users/second = 1000 database queries/second = 💀
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First request: GET /popular-products
→ Server runs the query (200ms)
→ Server stores the result in Redis with a 5-minute expiration
→ Returns result

Next 999 requests in 5 minutes:
→ Server checks Redis first (1ms)
→ Data is there! Returns it instantly
→ Database rests peacefully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cache Invalidation
&lt;/h3&gt;

&lt;p&gt;The hardest problem in caching: when do you update the cache? If you cache product prices and then change a price, users might see stale data. Strategies include time-based expiration (cache for 5 minutes), event-based invalidation (clear cache when data changes), and cache-aside (check cache first, fall back to database).&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Security Basics
&lt;/h2&gt;

&lt;p&gt;If you build a backend, you're responsible for protecting user data. Here are the most important threats:&lt;/p&gt;

&lt;h3&gt;
  
  
  SQL Injection
&lt;/h3&gt;

&lt;p&gt;The attacker puts SQL code inside your input fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;Login&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"admin@site.com"&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"' OR 1=1 --"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you build SQL strings by concatenating user input, this can expose your entire database. &lt;strong&gt;Never do this.&lt;/strong&gt; Always use &lt;strong&gt;parameterized queries&lt;/strong&gt; or your framework's ORM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Site Scripting (XSS)
&lt;/h3&gt;

&lt;p&gt;The attacker injects JavaScript into your site that runs in other users' browsers. For example, putting &lt;code&gt;&amp;lt;script&amp;gt;steal(cookies)&amp;lt;/script&amp;gt;&lt;/code&gt; in a comment field. &lt;strong&gt;Always sanitize user input&lt;/strong&gt; and escape HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Site Request Forgery (CSRF)
&lt;/h3&gt;

&lt;p&gt;The attacker tricks a logged-in user into making a request they didn't intend. Like clicking a link that secretly transfers money. &lt;strong&gt;Use CSRF tokens&lt;/strong&gt; — every framework has built-in protection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limiting
&lt;/h3&gt;

&lt;p&gt;Without rate limiting, someone can send millions of requests to your server (DDoS), or try millions of passwords (brute force). &lt;strong&gt;Limit how many requests one IP can make&lt;/strong&gt; per minute.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTPS Everywhere
&lt;/h3&gt;

&lt;p&gt;Always use HTTPS. Never HTTP. HTTPS encrypts data between the client and server so nobody in the middle can read it. Free certificates from Let's Encrypt make this a no-brainer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The OWASP Top 10
&lt;/h3&gt;

&lt;p&gt;OWASP maintains a list of the top 10 web security risks. Read it, understand it, and check your apps against it. This is a checklist every professional developer uses.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Architecture Patterns
&lt;/h2&gt;

&lt;p&gt;As your app grows, how you organize your code matters more and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monolith
&lt;/h3&gt;

&lt;p&gt;Everything in one big application. One codebase, one deployment. &lt;strong&gt;Start here.&lt;/strong&gt; It's simpler, easier to debug, and perfect for learning and small-to-medium apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices
&lt;/h3&gt;

&lt;p&gt;Breaking your app into small, independent services that communicate over the network. The Users service, Orders service, and Payments service are separate apps. &lt;strong&gt;Don't do this until you have a reason to.&lt;/strong&gt; It adds massive complexity. Companies like Netflix and Amazon use it because they have thousands of developers — not because it's always better.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVC (Model-View-Controller)
&lt;/h3&gt;

&lt;p&gt;The most common pattern inside any backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Represents your data (the User class, the Order class)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View:&lt;/strong&gt; What the user sees (HTML pages, or JSON responses for APIs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller:&lt;/strong&gt; Handles requests, calls the right models, returns the right views&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Almost every framework is built around MVC. Rails, Laravel, Django, Spring MVC — they're all variations of this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event-Driven Architecture
&lt;/h3&gt;

&lt;p&gt;Instead of services calling each other directly, they publish &lt;strong&gt;events&lt;/strong&gt; to a message queue (like RabbitMQ or Kafka). Other services listen and react.&lt;/p&gt;

&lt;p&gt;Example: When someone places an order, the Order Service publishes an "OrderPlaced" event. The Email Service hears it and sends a confirmation. The Inventory Service hears it and updates stock. They don't know about each other — they just react to events.&lt;/p&gt;

&lt;p&gt;This is an advanced pattern. Learn it conceptually now; implement it when you need it.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Networking Essentials
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The OSI Model (Simplified)
&lt;/h3&gt;

&lt;p&gt;You don't need to memorize all 7 layers. Just know the ones that matter for backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Application Layer (HTTP, HTTPS, WebSocket):&lt;/strong&gt; Where your code lives. You deal with requests and responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport Layer (TCP, UDP):&lt;/strong&gt; TCP guarantees delivery. UDP is faster but doesn't guarantee (used for video calls, gaming).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Layer (IP):&lt;/strong&gt; Routing data between machines using IP addresses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  WebSockets
&lt;/h3&gt;

&lt;p&gt;HTTP is one-way: client asks, server responds. But what about live chat, real-time notifications, or live scores? That's where WebSockets come in.&lt;/p&gt;

&lt;p&gt;A WebSocket is a persistent connection between client and server. Both can send messages at any time, without the client having to ask first. Think of HTTP as sending letters and WebSockets as a phone call — the line stays open.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Balancing
&lt;/h3&gt;

&lt;p&gt;When one server can't handle all the traffic, you add more servers and put a &lt;strong&gt;load balancer&lt;/strong&gt; in front of them. The load balancer distributes incoming requests across your servers. It's like having multiple checkout lines at a supermarket.&lt;/p&gt;

&lt;p&gt;Common strategies: round-robin (take turns), least connections (send to the least busy server), or IP hash (same user always goes to the same server).&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Linux &amp;amp; The Command Line
&lt;/h2&gt;

&lt;p&gt;Most servers run Linux. You don't need to be a Linux expert, but you need to be comfortable in the terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Essential Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Navigation&lt;/span&gt;
&lt;span class="nb"&gt;pwd&lt;/span&gt;                  &lt;span class="c"&gt;# Where am I?&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt;                   &lt;span class="c"&gt;# What's in this folder?&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/folder   &lt;span class="c"&gt;# Go to a folder&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..                &lt;span class="c"&gt;# Go up one level&lt;/span&gt;

&lt;span class="c"&gt;# Files&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;file.txt         &lt;span class="c"&gt;# Show file contents&lt;/span&gt;
nano file.txt        &lt;span class="c"&gt;# Edit a file&lt;/span&gt;
&lt;span class="nb"&gt;cp &lt;/span&gt;file.txt copy.txt &lt;span class="c"&gt;# Copy a file&lt;/span&gt;
&lt;span class="nb"&gt;mv &lt;/span&gt;old.txt new.txt   &lt;span class="c"&gt;# Rename/move&lt;/span&gt;
&lt;span class="nb"&gt;rm &lt;/span&gt;file.txt          &lt;span class="c"&gt;# Delete a file (careful!)&lt;/span&gt;

&lt;span class="c"&gt;# Searching&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt; log.txt &lt;span class="c"&gt;# Find lines containing "error"&lt;/span&gt;
find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.js"&lt;/span&gt;  &lt;span class="c"&gt;# Find all .js files&lt;/span&gt;

&lt;span class="c"&gt;# Processes&lt;/span&gt;
ps aux               &lt;span class="c"&gt;# Show running processes&lt;/span&gt;
top                  &lt;span class="c"&gt;# Live process monitor&lt;/span&gt;
&lt;span class="nb"&gt;kill &lt;/span&gt;1234            &lt;span class="c"&gt;# Kill process with ID 1234&lt;/span&gt;

&lt;span class="c"&gt;# Networking&lt;/span&gt;
curl http://example.com  &lt;span class="c"&gt;# Make an HTTP request&lt;/span&gt;
ping google.com          &lt;span class="c"&gt;# Check if a server is reachable&lt;/span&gt;

&lt;span class="c"&gt;# Permissions&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;755 script.sh  &lt;span class="c"&gt;# Make a script executable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Package Managers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu/Debian: &lt;code&gt;apt install package-name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;macOS: &lt;code&gt;brew install package-name&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SSH — Remote Server Access
&lt;/h3&gt;

&lt;p&gt;SSH (Secure Shell) lets you control a remote server from your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh user@123.45.67.89
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll use this constantly in your career to manage production servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Version Control (Git)
&lt;/h2&gt;

&lt;p&gt;Git tracks changes to your code. It's not optional — it's required for every developer job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository (Repo):&lt;/strong&gt; Your project folder, tracked by Git&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit:&lt;/strong&gt; A snapshot of your code at a point in time, with a message explaining what changed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branch:&lt;/strong&gt; A parallel version of your code. Work on features without affecting the main code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge:&lt;/strong&gt; Combining two branches together&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull Request (PR):&lt;/strong&gt; A proposal to merge your changes, reviewed by teammates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Essential Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init                    &lt;span class="c"&gt;# Start tracking a project&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;                   &lt;span class="c"&gt;# Stage all changes&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add login"&lt;/span&gt;   &lt;span class="c"&gt;# Save a snapshot&lt;/span&gt;
git branch feature-x        &lt;span class="c"&gt;# Create a new branch&lt;/span&gt;
git checkout feature-x      &lt;span class="c"&gt;# Switch to that branch&lt;/span&gt;
git merge feature-x         &lt;span class="c"&gt;# Merge feature-x into current branch&lt;/span&gt;
git push origin main        &lt;span class="c"&gt;# Upload to GitHub&lt;/span&gt;
git pull origin main        &lt;span class="c"&gt;# Download latest changes&lt;/span&gt;
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;           &lt;span class="c"&gt;# See commit history&lt;/span&gt;
git status                  &lt;span class="c"&gt;# See what's changed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Branching Strategy
&lt;/h3&gt;

&lt;p&gt;The most common: &lt;code&gt;main&lt;/code&gt; is production-ready. Create a branch for each feature. Merge back to &lt;code&gt;main&lt;/code&gt; via pull request after review. Never commit directly to &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  15. Testing
&lt;/h2&gt;

&lt;p&gt;Writing code that verifies your other code works correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of Tests
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit Tests:&lt;/strong&gt; Test a single function in isolation. "Does my &lt;code&gt;calculateTax(100)&lt;/code&gt; return &lt;code&gt;15&lt;/code&gt;?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Tests:&lt;/strong&gt; Test multiple pieces working together. "Does my API endpoint actually save to the database and return the right response?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-End (E2E) Tests:&lt;/strong&gt; Test the whole system from the user's perspective. "Can a user sign up, log in, and place an order?"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Testing Pyramid
&lt;/h3&gt;

&lt;p&gt;Write &lt;strong&gt;many&lt;/strong&gt; unit tests (fast, cheap), &lt;strong&gt;some&lt;/strong&gt; integration tests (medium), and &lt;strong&gt;few&lt;/strong&gt; E2E tests (slow, expensive). Most of your bugs will be caught by unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Testing Matters
&lt;/h3&gt;

&lt;p&gt;Without tests, every change you make could break something else without you knowing. With tests, you change code confidently. Tests are your safety net. Every serious company requires them.&lt;/p&gt;




&lt;h2&gt;
  
  
  16. DevOps Basics
&lt;/h2&gt;

&lt;p&gt;DevOps is the bridge between writing code and running code in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker — Portable Environments
&lt;/h3&gt;

&lt;p&gt;Docker packages your app and all its dependencies into a &lt;strong&gt;container&lt;/strong&gt;. "It works on my machine" becomes "it works everywhere."&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Dockerfile&lt;/code&gt; is a recipe for building your container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now anyone can run your app with: &lt;code&gt;docker build -t myapp . &amp;amp;&amp;amp; docker run myapp&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD — Automated Testing &amp;amp; Deployment
&lt;/h3&gt;

&lt;p&gt;CI (Continuous Integration): Every time you push code, automated tests run. If they fail, you know before the code reaches production.&lt;/p&gt;

&lt;p&gt;CD (Continuous Deployment): If tests pass, the code automatically gets deployed to production. No manual steps.&lt;/p&gt;

&lt;p&gt;Tools: GitHub Actions, GitLab CI, Jenkins. GitHub Actions is the easiest to start with.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Basics
&lt;/h3&gt;

&lt;p&gt;Your server needs to live somewhere. The big three cloud providers are AWS (Amazon), GCP (Google), and Azure (Microsoft). For starting out, simpler platforms like Railway, Render, or Fly.io let you deploy without cloud complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  17. The Learning Order (Roadmap)
&lt;/h2&gt;

&lt;p&gt;Here's the order that makes sense. Don't jump ahead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: The Foundation (Weeks 1–6)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Pick ONE language (JavaScript/Node.js or Python — both are great)&lt;/li&gt;
&lt;li&gt;Learn programming basics: variables, functions, loops, arrays, objects, classes&lt;/li&gt;
&lt;li&gt;Understand how the internet works: HTTP, DNS, TCP/IP&lt;/li&gt;
&lt;li&gt;Learn the command line basics&lt;/li&gt;
&lt;li&gt;Learn Git basics&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 2: Databases &amp;amp; APIs (Weeks 7–12)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Learn SQL (PostgreSQL recommended)&lt;/li&gt;
&lt;li&gt;Build a simple REST API with your language (Express for Node.js, Flask/FastAPI for Python)&lt;/li&gt;
&lt;li&gt;Connect your API to a database&lt;/li&gt;
&lt;li&gt;Learn about request/response, routing, middleware&lt;/li&gt;
&lt;li&gt;Build a CRUD app (Create, Read, Update, Delete) — like a todo list or blog&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 3: Real-World Skills (Weeks 13–20)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add authentication (JWT, password hashing)&lt;/li&gt;
&lt;li&gt;Learn about validation and error handling&lt;/li&gt;
&lt;li&gt;Add caching (Redis)&lt;/li&gt;
&lt;li&gt;Learn basic security (SQL injection, XSS, CSRF)&lt;/li&gt;
&lt;li&gt;Write unit tests&lt;/li&gt;
&lt;li&gt;Build a bigger project (e-commerce API, social media API)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 4: Production &amp;amp; Scale (Weeks 21–28)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Learn Docker&lt;/li&gt;
&lt;li&gt;Deploy your app to the cloud&lt;/li&gt;
&lt;li&gt;Set up CI/CD with GitHub Actions&lt;/li&gt;
&lt;li&gt;Learn about logging and monitoring&lt;/li&gt;
&lt;li&gt;Understand basic architecture patterns (MVC, microservices concepts)&lt;/li&gt;
&lt;li&gt;Study system design basics&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 5: Level Up (Ongoing)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Learn a second framework to prove your concepts transfer&lt;/li&gt;
&lt;li&gt;Study message queues (RabbitMQ/Kafka)&lt;/li&gt;
&lt;li&gt;Learn GraphQL&lt;/li&gt;
&lt;li&gt;Dive deeper into system design&lt;/li&gt;
&lt;li&gt;Contribute to open source&lt;/li&gt;
&lt;li&gt;Read other people's code&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🎯 The Big Takeaway
&lt;/h2&gt;

&lt;p&gt;Frameworks change every few years. JavaScript frameworks are born and die faster than you can learn them. But the concepts in this guide? They've been the same for &lt;strong&gt;decades&lt;/strong&gt; and will stay the same for decades more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP hasn't changed.&lt;/strong&gt; Databases still use SQL. Servers still handle request→process→response. Auth still uses tokens or sessions. Caching still makes things fast.&lt;/p&gt;

&lt;p&gt;When you understand these fundamentals, picking up a new framework takes days, not months. You look at Spring and think "Oh, this is just their way of doing routing and middleware." You look at Django and think "This is just MVC with a different name."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're not learning a framework. You're learning how computers talk to each other.&lt;/strong&gt; The framework is just the language you write it in.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The person who understands WHY will always lead the person who only knows HOW."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good luck on your journey. You've already made the right decision by starting with the fundamentals. 🚀&lt;/p&gt;

&lt;p&gt;&lt;em&gt;credits: claude&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>learning</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
