<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Interviews - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Interviews - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 19 Jun 2026 22:33:46 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/interviews/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Prepare for Your JavaScript Interview ]]>
                </title>
                <description>
                    <![CDATA[ Are you preparing for a JavaScript interview and want to ensure that you have a deep understanding of closures, functions, and currying? Then Roadside Coder's video course is just what you need. We just published a full course on the freeCodeCamp.org... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/prepare-for-your-javascript-interview/</link>
                <guid isPermaLink="false">66b20612f31aa965000e5878</guid>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 20 Apr 2023 17:04:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/jsfunctions.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you preparing for a JavaScript interview and want to ensure that you have a deep understanding of closures, functions, and currying? Then Roadside Coder's video course is just what you need.</p>
<p>We just published a full course on the freeCodeCamp.org YouTube channel that will help prepare you for a JavaScript technical interview.</p>
<p>In this comprehensive course, you'll learn about various aspects of JavaScript, including function declarations, expressions, scopes, and hoisting, as well as advanced concepts like closures and lexical scope. You'll also gain an understanding of currying and its practical applications in JavaScript.</p>
<p>The course begins with an introduction and an overview of function declarations and expressions, anonymous functions, and first-class functions. You'll also learn about Immediately Invoked Function Expressions (IIFE) and how they can be used in interviews. The course then delves into closures and function scopes, including hoisting and parameter vs. argument differences.</p>
<p>The course also covers callback functions, arrow functions, and lexical scope. You'll learn how to implement closures and apply them in practical situations. With a series of interview questions and exercises, you'll also have the chance to test your knowledge and apply what you've learned.</p>
<p>In addition to closures, the course covers the concept of currying and its various applications. You'll learn what currying is and how to use it in various situations, such as reusing variables for logic, infinite currying, manipulating the DOM, and partial application.</p>
<p>Roadside Coder, a full-stack developer and popular course creator, guides you through each section of the course with clear and concise instructions. He breaks down complex concepts into easily understandable terms, making the course suitable for both beginners and experienced developers looking to improve their JavaScript knowledge.</p>
<p>By the end of the course, you'll have a deep understanding of closures, functions, and currying, as well as the ability to apply this knowledge in practical situations. You'll also be well-equipped to answer JavaScript interview questions related to closures and functions.</p>
<p>Watch the full course on <a target="_blank" href="https://www.youtube.com/watch?v=tbqVqP5ilzQ">the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tbqVqP5ilzQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Problem Solving Patterns for Technical Interviews: the Frequency Counter Pattern Explained ]]>
                </title>
                <description>
                    <![CDATA[ By Martin Cartledge In my last article, I shared my thoughts on how to prepare for a software developer interview.  In this article, I am going to switch gears a bit and talk about common patterns you can use to solve problems in technical interviews... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/solve-technical-interview-questions-using-frequency-counter/</link>
                <guid isPermaLink="false">66d4601a51f567b42d9f8493</guid>
                
                    <category>
                        <![CDATA[ career advice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ careers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interview tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 18 Dec 2020 21:48:23 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/beach.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Martin Cartledge</p>
<p>In my last article, I shared my thoughts on how to <a target="_blank" href="https://www.martincartledge.io/prepare-for-software-developer-interview/">prepare for a software developer interview</a>. </p>
<p>In this article, I am going to switch gears a bit and talk about common patterns you can use to solve problems in technical interviews. We'll discuss the <em>frequency counter</em> pattern in depth to help you tackle it effectively.</p>
<h2 id="heading-what-is-the-frequency-counter-pattern">What is the “Frequency Counter” pattern?</h2>
<p>The Frequency Counter pattern uses an object or set to collect values and the frequency of those values.</p>
<p>This pattern is often used with an <code>array</code> or a <code>string</code>, and allows you to avoid nested loops (quadratic time complexity <code>O(n²)</code>).</p>
<h2 id="heading-when-should-i-use-the-frequency-counter-pattern">When should I use the Frequency Counter pattern?</h2>
<p>The Frequency Counter pattern is most helpful when you have multiple pieces of data that you want to compare with one another. Let me walk you through an example to see the Frequency Counter in action.</p>
<h2 id="heading-the-samesquared-exercise">The "sameSquared" exercise</h2>
<ul>
<li>Write a function called <code>sameSquared</code> which accepts two arrays</li>
<li>The function should return <code>true</code> if <em>every</em> value in the first array has its corresponding value squared in the second array</li>
<li>The frequency of the values must be the same</li>
</ul>
<h3 id="heading-what-is-the-optimal-outcome">What is the optimal outcome?</h3>
<p>After our function is written, we should expect our <code>sameSquared</code> function to return these values.</p>
<p><code>sameSquared([1, 2, 3], [4, 1, 9]); _// true_</code></p>
<p><code>sameSquared([1, 2, 3], [1, 9]); _// false_</code></p>
<p><code>sameSquared([1, 2, 1], [4, 4, 1]); _// false_</code></p>
<p><code>sameSquared([2, 3, 6, 8, 8], [64, 36, 4, 9, 64]); _// true_</code></p>
<h3 id="heading-getting-started">Getting started</h3>
<p>First, using the <code>function</code> keyword, we create a function with the identifier <code>sameSquared</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params"></span>) </span>{
</code></pre>
<p>Our function <code>sameSquared</code> needs two parameters, a first array and a second array. In this example, we are passing these values <code>[1, 2, 3]</code> and <code>[4, 1, 9]</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
</code></pre>
<h3 id="heading-check-edge-cases">Check edge cases</h3>
<p>Inside of our function block, we want to address a few edge cases. First, we need to check that both parameters have truthy values, that is <em>not</em> <code>null</code>, <code>undefined</code>, and so on. </p>
<p>We can check for a falsy value by using the <code>!</code> operator. If <code>firstArr</code> or <code>secondArr</code> is falsy, we return <code>false</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</code></pre>
<p>The next edge case we want to account for is to ensure that the length of both arrays are the same. If they are different, we know that they can <em>not</em> contain an equal amount of shared values.</p>
<p>By checking the <code>length</code> property on both parameters, we can determine if they are the same. If they are not, we return <code>false</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstArr.length !== secondArr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</code></pre>
<h3 id="heading-build-a-dictionary-to-avoid-nested-loops">Build a "dictionary" to avoid nested loops</h3>
<p>We need to keep track of all values in at least one of the arrays. To do this, and to avoid a nested loop, we can store these values in a hash table (object). I’ll call mine <code>lookup</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstArr.length !== secondArr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};
</code></pre>
<p>Using a <code>for of</code> loop, we iterate through the <code>firstArr</code>. Inside of the <code>for of</code> block, we assign the key to the result of <code>value * value</code>.</p>
<p>The value in this key/value pair will be a <em>frequency counter</em> that reflects how many times a specific value is “seen” in the <code>firstArr</code>.</p>
<p>First, we check if <code>lookup</code> contains an entry for <code>value * value</code>, if it does, we add <code>1</code> to it. If it does not, we assign the value to <code>0</code> and then add <code>1</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstArr.length !== secondArr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};

  <span class="hljs-keyword">for</span> (value <span class="hljs-keyword">of</span> firstArr) {
    lookup[value * value] = (lookup[value * value] || <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>;
  }
</code></pre>
<p>Once the <code>firstArr</code> is finished looping, the <code>lookup</code> should contain these values:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-number">1</span>: <span class="hljs-number">1</span>,
  <span class="hljs-number">4</span>: <span class="hljs-number">1</span>,
  <span class="hljs-number">9</span>: <span class="hljs-number">1</span>
}
</code></pre>
<h3 id="heading-compare-array-values">Compare array values</h3>
<p>Now that we have iterated through all of the values in the <code>firstArr</code> and stored them as their respective <em>squared</em> value, we want to compare those values to the values in the <code>secondArr</code>.</p>
<p>We start by creating another <code>for of</code> loop. On the first line inside of our new <code>for of</code> block, we write a conditional statement to check if the current value from our <code>secondArr</code> is <em>not</em> inside of our <code>lookup</code>. If it is not, we stop looping and return <code>false</code>.</p>
<p>If the value from the <code>secondArr</code> is in our <code>lookup</code>, we want to decrement the value of that entry. We can do so by using the <code>-=</code> assignment operator.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstArr.length !== secondArr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};
  <span class="hljs-keyword">for</span> (value <span class="hljs-keyword">of</span> firstArr) {
    lookup[value * value] = (lookup[value * value] || <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>;
  }
  <span class="hljs-keyword">for</span> (secondValue <span class="hljs-keyword">of</span> secondArr) {
    <span class="hljs-keyword">if</span> (!lookup[secondValue]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
      lookup[secondValue] -= <span class="hljs-number">1</span>;
    }
</code></pre>
<p>After we are finished looping through the <code>secondArr</code>, our <code>lookup</code> should have these values:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-number">1</span>: <span class="hljs-number">0</span>,
  <span class="hljs-number">4</span>: <span class="hljs-number">0</span>,
  <span class="hljs-number">9</span>: <span class="hljs-number">0</span>
}
</code></pre>
<h3 id="heading-wrapping-up-our-samesquared-function">Wrapping up our "sameSquared" function</h3>
<p>If we finish iterating through the <code>secondArr</code> without returning <code>false</code>, that means that our <code>firstArr</code> contains all values that are in a squared state in the <code>secondArr</code>. Therefore, we return <code>true</code> outside of <code>for of</code> loop.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sameSquared</span>(<span class="hljs-params">firstArr, secondArr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstArr || !secondArr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstArr.length !== secondArr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};
  <span class="hljs-keyword">for</span> (value <span class="hljs-keyword">of</span> firstArr) {
    lookup[value * value] = (lookup[value * value] || <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>;
  }
  <span class="hljs-keyword">for</span> (secondValue <span class="hljs-keyword">of</span> secondArr) {
    <span class="hljs-keyword">if</span> (!lookup[secondValue]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    lookup[secondValue] -= <span class="hljs-number">1</span>;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>Let me show you another example which is used very commonly in coding assessments (so you might’ve seen this problem before).</p>
<h2 id="heading-the-isanagram-exercise">The "isAnagram" exercise</h2>
<ul>
<li>Write a function called <code>isAnagram</code> which accepts two strings</li>
<li>The function should return <code>true</code> if the two strings parameters are <a target="_blank" href="https://en.wikipedia.org/wiki/Anagram">anagrams</a> of each other</li>
</ul>
<h3 id="heading-what-is-the-optimal-outcome-1">What is the optimal outcome?</h3>
<p>After our function is written, we should expect our <code>isAnagram</code> function to return these values.</p>
<p><code>isAnagram(“silent”, “listen”); _// true_</code></p>
<p><code>isAnagram(“martin”, “nitram”); _// true_</code></p>
<p><code>isAnagram(“cat”, “tag”); _// false_</code></p>
<p><code>isAnagram(“rat”, “tar”); _// true_</code></p>
<h3 id="heading-getting-started-1">Getting started</h3>
<p>First, using the <code>function</code> keyword, we create a function with the identifier <code>isAnagram</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params"></span>) </span>{
</code></pre>
<p>Our function <code>isAnagram</code> needs two parameters, a first <code>string</code> and a second <code>string</code>. In this example, we are passing these value, <code>silent</code> and <code>listen</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
</code></pre>
<h3 id="heading-check-edge-cases-1">Check edge cases</h3>
<p>On the first few lines of our function block, we want to address a few edge cases, just like in the first example. </p>
<p>Similar to <code>isAnagram</code>, we need to check that both parameters have truthy values, that is <em>not</em> <code>null</code>, <code>undefined</code>, and so on. We can check for a falsy value by using the <code>!</code> operator. If <code>firstStr</code> or <code>secondStr</code> is falsy, we return <code>false</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</code></pre>
<p>The next edge case we want to account for is to ensure that the length of both arrays are the same. If they are different, we know that they can <em>not</em> contain an equal number of shared values.</p>
<p>By checking the <code>length</code> property on both parameters, we can determine if they are the same. If they are not, we return <code>false</code></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstStr.length !== secondStr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</code></pre>
<h3 id="heading-build-a-dictionary-to-avoid-nested-loops-1">Build a "dictionary" to avoid nested loops</h3>
<p>Remember, we are using the frequency counter pattern and we need to keep track of all values in at least one of the arrays. Now we know that the best way to handle this is to store these values in a hash table (object). To keep things consistent, I’ll call mine <code>lookup</code> again.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstStr.length !== secondStr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};
</code></pre>
<p>Using a <code>for of</code> loop, we iterate through the <code>firstStr</code>. Inside of the <code>for of</code> block, we assign the key to the result of the expression <code>value * value</code>.</p>
<p>The value in this key/value pair will be a <em>frequency counter</em> that reflects how many times a specific value is “seen” in the <code>firstStr</code>.</p>
<p>Using a ternary operator, we check if <code>lookup</code> contains an entry for <code>value * value</code>, if it does, we use the <code>+=</code> assignment operator to increment the value by <code>1</code>. If it does not, we simply assign the value to <code>1</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
    <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">if</span> (firstStr.length !== secondStr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">const</span> lookup = {};

    <span class="hljs-keyword">for</span> (first <span class="hljs-keyword">of</span> firstStr) {

        lookup[first] ? (lookup[first] += <span class="hljs-number">1</span>) : (lookup[first] = <span class="hljs-number">1</span>);

  }
</code></pre>
<p>Once the <code>firstStr</code> is finished looping, the <code>lookup</code> should contain these values:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">s</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">i</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">l</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">e</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">n</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">t</span>: <span class="hljs-number">1</span>
}
</code></pre>
<h3 id="heading-compare-array-values-1">Compare array values</h3>
<p>Now that we have iterated through all of the values in the <code>firstStr</code> and stored their values, we want to compare those values to the values in the <code>secondStr</code>.</p>
<p>We start by creating another <code>for of</code> loop. On the first line inside of our new <code>for of</code> block, we write a conditional statement to check if the current value from our <code>secondStr</code> is <em>not</em> inside of our <code>lookup</code>. If it is not, we want to stop iteration and return <code>false</code>.</p>
<p>Otherwise, if the value from the <code>secondStr</code> <em>is</em> in our <code>lookup</code>, we want to decrement the value of that entry. We can do so by using the <code>-=</code> assignment operator.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstStr.length !== secondStr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};

  <span class="hljs-keyword">for</span> (first <span class="hljs-keyword">of</span> firstStr) {
    lookup[first] ? (lookup[first] += <span class="hljs-number">1</span>) : (lookup[first] = <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">for</span> (second <span class="hljs-keyword">of</span> secondStr) {
    <span class="hljs-keyword">if</span> (!lookup[second]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    lookup[second] -= <span class="hljs-number">1</span>;
  }
</code></pre>
<p>After we are finished looping through the <code>secondStr</code>, our <code>lookup</code> should have these values:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">s</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">i</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">l</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">e</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">n</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">t</span>: <span class="hljs-number">0</span>
}
</code></pre>
<h3 id="heading-wrapping-up-our-isanagram-function">Wrapping up our "isAnagram" function</h3>
<p>If we finish iterating through the <code>secondStr</code> without returning <code>false</code>, that means that our <code>firstStr</code> contains all values that are in the <code>secondStr</code>. Therefore, we return <code>true</code> outside of <code>for of</code> loop.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isAnagram</span>(<span class="hljs-params">firstStr, secondStr</span>) </span>{
  <span class="hljs-keyword">if</span> (!firstStr || !secondStr) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">if</span> (firstStr.length !== secondStr.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">const</span> lookup = {};

  <span class="hljs-keyword">for</span> (first <span class="hljs-keyword">of</span> firstStr) {
    lookup[first] ? (lookup[first] += <span class="hljs-number">1</span>) : (lookup[first] = <span class="hljs-number">1</span>);
  }

  <span class="hljs-keyword">for</span> (second <span class="hljs-keyword">of</span> secondStr) {
    <span class="hljs-keyword">if</span> (!lookup[second]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    lookup[second] -= <span class="hljs-number">1</span>;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<h2 id="heading-in-summary">In Summary</h2>
<p>I hope this in-depth overview of the Frequency Counter pattern was helpful. Now that you know how the pattern works, I am confident that you will be able to impress your interviewer by showcasing your skills at an even higher level.</p>
<p>In my next article, I will be discussing another common problem-solving pattern called the Sliding Window. Thanks for reading, and happy interviewing!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get an Interview as a Software Developer ]]>
                </title>
                <description>
                    <![CDATA[ By Martin Cartledge In this article, I will share the steps you should take to increase your chances of getting an interview as a software developer.  Whether you are just starting out, or looking for something new, I am confident that you will find ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-an-interview-as-a-software-developer/</link>
                <guid isPermaLink="false">66d46014052ad259f07e4b14</guid>
                
                    <category>
                        <![CDATA[ careers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interview tips ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 30 Nov 2020 19:43:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/11/dog_at_beach-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Martin Cartledge</p>
<p>In this article, I will share the steps you should take to increase your chances of getting an interview as a software developer. </p>
<p>Whether you are just starting out, or looking for something new, I am confident that you will find value in what I share below. </p>
<p>I'll be sharing other <em>interview insights</em> in future articles, as well. So look out for them over the coming weeks.</p>
<p>Alright, let’s get started!</p>
<h2 id="heading-how-to-determine-your-ideal-role">How to determine your ideal role</h2>
<p>This might sound strange, but I think it is a question that is often overlooked. </p>
<p>Due to the eclectic nature of our industry, it is common to just apply to <em>any</em> kind of job. </p>
<p>This is tricky because, on the one hand, you want interviews and experience with different technologies. But I have found that answering a few questions can put you ahead in your search. So what are those questions?</p>
<h3 id="heading-what-kind-of-developer-do-you-want-to-be">What kind of developer do you want to be?</h3>
<p>If you are looking for your first job, this might be the hardest question you have to answer. </p>
<p>Although this might seem overly simplified, I do think it is most important to pick a niche of software that makes <em>you happy</em>. After all, you are the one that will be doing this work 40 hours a week, right?</p>
<p>If you are brand new to software development and are not sure what you like best, I suggest browsing <a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a>, <a target="_blank" href="https://www.codecademy.com/">Code Academy</a>, <a target="_blank" href="https://teamtreehouse.com/">Treehouse</a>, or <a target="_blank" href="https://www.udemy.com/">Udemy</a>. Then take a course that sounds interesting to you.</p>
<p>It is easy to get caught in a state of limbo when you are not sure what to do next. My advice when that happens is to just pick something and try it.</p>
<h3 id="heading-what-kind-of-company-do-you-want-to-work-for">What kind of company do you want to work for?</h3>
<p>This might be a tricky question to answer, but it can really save you lots of headaches down the road. </p>
<p>In software development, there are typically three <em>types</em> of companies:</p>
<h4 id="heading-startups">Startups</h4>
<p>Startups typically have under 500 employees, are less than 5 years old, and embrace a fast-paced environment.</p>
<p>Pros:</p>
<ul>
<li>You will play a large role in the problems that your company is trying to solve</li>
<li>You'll work with cutting edge technology in the industry</li>
<li>There will be lots of opportunities to learn from senior developers</li>
</ul>
<p>Cons:</p>
<ul>
<li>You'll be responsible for (you'll “own”) more pieces of the codebase</li>
<li>Processes such as code review and a team code style might not be established</li>
<li>You might have to quickly throw out code you contributed to because the team is trying out other ideas</li>
</ul>
<h4 id="heading-mid-sized-companies">Mid-sized companies</h4>
<p>A mid-sized company will typically have 500–5,000 employees and be at least 5 years old.</p>
<p>Pros:</p>
<ul>
<li>There's a high chance that the company will be profitable (job security)</li>
<li>There will be more onboarding resources and documentation</li>
<li>You'll have solidified planning strategies and clear goals for each quarter</li>
</ul>
<p>Cons:</p>
<ul>
<li>More processes can mean more meetings and less time spent coding</li>
<li>A larger team can mean less individual input/direction of a project</li>
<li>It can be harder to adopt newer technologies due to legacy applications, and so on</li>
</ul>
<h4 id="heading-large-corporations">Large corporations</h4>
<p>Large corporations typically have 5,000+ employees and are over 10 years old.</p>
<p>Pros:</p>
<ul>
<li>They usually have the resources to pay higher salaries</li>
<li>Traditionally there's a more vetted process to get hired, and so lots of opportunity to learn from team members</li>
<li>Stock options (you benefit when your company benefits)</li>
</ul>
<p>Cons:</p>
<ul>
<li>It tends to feel like you are a small fish in a large pond (contributions are not as tangible)</li>
<li>Career advancement (like promotions or switching teams) can be a long-winded process</li>
<li>It's often harder to bond as a team if you're globally distributed</li>
</ul>
<p>All of these factors are good things to keep in mind when you're looking to switch companies or if you are looking to join your first company. </p>
<h3 id="heading-how-do-you-learn-more-about-a-company">How do you learn more about a company?</h3>
<p>A lot of resources have surfaced over the last 5–10 years that help folks get an “inside view” into a company’s interview process, culture, and salaries. A few that are particularly useful are:</p>
<ul>
<li><a target="_blank" href="https://www.glassdoor.com/">Glassdoor</a>: Employee reviews, interview experiences, and common salaries</li>
<li><a target="_blank" href="https://www.teamblind.com/">Blind</a>: Anonymous employee reviews, interview experiences, common salaries, and employee referrals</li>
<li><a target="_blank" href="https://www.levels.fyi/">Levels.fyi</a>: Title hierarchy, title comparisons to other companies, and common salaries</li>
</ul>
<p>Once you've answered these questions and figured out what sort of company you want to work for, and in what kind of role, you're ready to prepare for the job hunt. So what does that involve?</p>
<h2 id="heading-update-your-resume">Update Your Résumé</h2>
<p>I like to think that everyone on the job hunt has a personal billboard that they carry around with them. You can write on it, or decorate it however you like. That billboard is your résumé.</p>
<p>What you decide to put on your personal billboard will greatly affect your chances of getting an interview or not. So here are some things to keep in mind when writing a résumé:</p>
<ul>
<li>Keep it short (1 page, or 2 pages if you have 10+ years of experience)</li>
<li>Tailor your resume to the job you want</li>
<li>If past technology/experience is not applicable, try to make it applicable or leave it out</li>
<li>Write 3–5 bullet points for each job</li>
<li>Make your contributions impactful by using metrics (Wrote a function that processed 10,000k data points, cut down on processing time by 60%, and so on)</li>
</ul>
<p>Keep in mind that a recruiter or HR representative will only spend 10–15 seconds (at most) scanning your résumé, so you do not have much time. You want to make sure you include details that will help illustrate that you can help this company.</p>
<p>With that being said, a few things you might want to leave out are:</p>
<ul>
<li>A personal photo</li>
</ul>
<p><em>Instead</em>: Make your name and the position you <em>want</em> catch the reader's eye</p>
<ul>
<li>Graph representations of skill level</li>
</ul>
<p><em>Instead</em>: Try replacing it with a sorted list of technologies, starting with your highest comfort level</p>
<p><em>Or</em>: List your skills in alphabetical order and make your best skills <strong>bold</strong></p>
<ul>
<li>Listing jobs that are not relevant to the career field</li>
</ul>
<p><em>Instead</em>: Use that space to expand on the experience you have in the software industry. If you don’t have much experience yet, this is a great place to expand on a project(s) you have worked on.</p>
<h3 id="heading-try-out-your-resume-on-a-friend-or-tool">Try out your résumé on a friend (or tool)</h3>
<p>Another great way to determine if your résumé conveys what you would like it to is to have a friend read it for 15 seconds. </p>
<p>After that time is up, take the résumé and have them tell you what they remembered from it. This can be a company name, skill, or contact information. </p>
<p>This is a great trial run to determine what grabs a person’s eye when they scan your résumé.</p>
<p>Here are some helpful tools to improve your résumé:</p>
<ul>
<li><a target="_blank" href="https://www.grammarly.com/">Grammarly</a></li>
<li><a target="_blank" href="https://docs.google.com/document/d/1ARVyybC5qQEiCzUOLElwAdPpKOK0Qf88srr682eHdCQ/edit">Google Drive Resume Template (Serif)</a></li>
<li><a target="_blank" href="https://docs.google.com/document/d/1WR_axh5A9t1jwER_5mFCIcr5I1oNqm4cB1PHAQEEWqc/edit">Google Drive Resume Template (Swiss)</a></li>
</ul>
<h2 id="heading-how-to-conquer-the-job-hunt">How to Conquer the Job Hunt</h2>
<blockquote>
<p><em>"By failing to prepare you are preparing to fail." - Benjamin Franklin</em></p>
</blockquote>
<p>Let’s just face it: the job hunt is an exhausting and grueling affair for most. I have found that the best way to approach the job search is to have two important things before you start:</p>
<ul>
<li>Goals (daily and weekly)</li>
<li>A plan of action (daily and weekly)</li>
</ul>
<p>Let's talk about how you can establish both.</p>
<h3 id="heading-set-goals-and-create-a-plan">Set Goals and Create a Plan</h3>
<p>I know what you are thinking: <em>ummm, my goal is to get a new job?</em> Of course, this is the end goal. But, in my experience, spending the time to determine what your goals are early is a great way to feel productive and confident. </p>
<p>The reason I break down these goals into two categories is that it is important to feel like you are being productive every day, even if you are not getting emails or calls back.</p>
<p>Some examples I have used in the past for daily and weekly goals are:</p>
<h4 id="heading-daily-goals">Daily Goals:</h4>
<ul>
<li>Submit 10 applications</li>
<li>Spend 30 minutes on a side project</li>
</ul>
<h4 id="heading-weekly-goals">Weekly Goals:</h4>
<ul>
<li>Schedule a phone interview</li>
<li>Spend 2 hours on technical interview prep</li>
</ul>
<p>These might seem overly simplified, and you’re right! That is the idea. You want to make sure you make your daily and weekly goals are things that are easily measurable, and <em>sustainable</em>.</p>
<h2 id="heading-make-the-most-of-your-time">Make the Most of Your Time</h2>
<p>So far we have talked about the importance of determining your ideal role, refining your résumé, and setting a schedule for yourself. To ensure that these tasks are not wasted effort, you want to make sure you are making the most of your time.</p>
<p>What do I mean by that? Think of the old sayings <em>Set yourself up for success</em> or <em>Put the right foot forward</em>. Basically, you want to make sure you are equally balanced in your journey to getting more interviews and being successful at them.</p>
<p>Besides doing the items mentioned above, a few others that can carry great importance are:</p>
<ul>
<li>Practice what you're learning (and what you already know)</li>
<li>Work on side projects</li>
<li>Develop an online presence</li>
</ul>
<h3 id="heading-practice-what-youre-learning">Practice What You're Learning</h3>
<p>Out of all the things I mention in this post, this one should come as the least surprising.</p>
<p>To get better at coding, problem-solving, interviewing, or underwater basket weaving, you have to <em>practice.</em> A LOT. There is no getting around this step. </p>
<p>I, like many, have fallen victim to a cycle of planning too much, taking too many tutorials, or telling myself <em>I’ll start tomorrow</em>.</p>
<p>For me, this was, and still is the hardest part about preparing for interviews, or quite honestly just being in this industry in general. Things move really quickly, and no one wants to feel like they are falling behind. </p>
<p>But, tech is a mentally draining profession. It is more than understandable that the thought of practicing coding interview questions in any capacity is exhausting. </p>
<p>I have some good news, though. When you think about practicing, try to think of your current skills as water in a bucket. Each time you practice, even something you think is small or not enough, think of that as drops of water that fill your bucket.</p>
<p>All experiences, good or bad, frustrating or rewarding, fill this bucket up and make <em>you</em> a stronger developer <em>every day</em>.</p>
<p>I think a great way to get into the habit of practicing writing code is to give yourself a goal per week. Remember, the ultimate goal is to practice and stay consistent, so avoid setting the bar at an unrealistic level for yourself. All this will do is make you feel bad on days you just don’t feel like coding.</p>
<p>Remember, you are the only person like <em>you</em>. There will never be anyone else like you, and that is awesome. So be nice to yourself, this stuff is hard. </p>
<p>If you make a habit to practice just a little bit, each time that bucket will fill up and you will surprise yourself after just a few weeks of staying consistent. You got this!</p>
<p>Here are some helpful tools to get you in the habit of practicing consistently:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a></li>
<li><a target="_blank" href="https://leetcode.com/">Leetcode</a></li>
<li><a target="_blank" href="https://www.codecademy.com/">Code Academy</a></li>
</ul>
<h3 id="heading-work-on-side-projects">Work on Side Projects</h3>
<p>This is something else that I am sure you have heard a million times. But I do think that working on a side project can really help you stand out as a candidate. And it'll also help you stay engaged on days you don’t feel like practicing your coding skills.</p>
<p>In my experience, it has been easier to get started when you can think of answers to both of these questions:</p>
<ul>
<li>What tech do I want to learn or get better at?</li>
<li>What is a product I really like, or I wish existed?</li>
</ul>
<p>With the answer to these two questions, you have a framework for your project! Do you like the new look of Twitter? Pick a feature and try to recreate the look and feel of it. Can’t find a habit tracker app you like? Try building one yourself.</p>
<p>If you would prefer to contribute to a project that is already established, that’s great as well. This can be a daunting task if it is your first time. But <a target="_blank" href="https://firstcontributions.github.io/">there is a great website</a> that lists tons of projects on Github that are looking for first-time contributors. So check it out.</p>
<p>Here are some other helpful tools:</p>
<ul>
<li><a target="_blank" href="https://medium.com/better-programming/12-ideas-for-programming-projects-too-dangerous-not-to-build-514e3212ab77">“12 Great Ideas for Programming Projects That People Will Use” by Filipe Silva</a></li>
<li><a target="_blank" href="https://github.com/florinpop17/app-ideas">“app-ideas” repo by Florin Pop</a></li>
</ul>
<h3 id="heading-develop-an-online-presence">Develop an Online Presence</h3>
<p>I like to think of the web as another place that allows us to have our own “personal billboard”. There are many advantages to having a solid presence online, and some of them include:</p>
<ul>
<li>Networking / meeting other developers</li>
<li>Showing off projects</li>
<li>Getting potential interest from other companies</li>
</ul>
<p>Putting in the extra effort to make your online presence solid can take you a long way, and the ways you can achieve this are relatively straightforward. Here are a few things I suggest you do:</p>
<h4 id="heading-build-a-portfolio-site">Build a portfolio site</h4>
<p>This does not have to be an extravagant, complicated website if you do not want it to be. As long as it has contact information, links to your various profiles, and a blurb about yourself you should be good-to-go. </p>
<p>This can be a great place to showcase your technical skills or talk about your passions and work history, too.</p>
<h4 id="heading-get-a-personalized-url">Get a personalized URL</h4>
<p>A lot of common websites that developers use (like Github, LinkedIn, Medium, Dev.to, Twitter, and others) allow you to change your URL. I suggest you make it your user name. I would also suggest trying to use the same name for each website.</p>
<h4 id="heading-start-a-blog">Start a blog</h4>
<p>If you are not interested in building projects and would prefer writing, this is a great way to show your skills and build an audience.</p>
<h4 id="heading-have-a-consistent-profile-photo">Have a consistent profile photo</h4>
<p>Ideally you want to use a photo that is professional, but lets your personality shine through as well. Once you find one, try to use that same photo across all your sites/social media profiles.</p>
<h3 id="heading-be-active-on-social-media">Be active on social media</h3>
<p>This is certainly not a requirement, but if you want to leverage social media as a platform for your development, I suggest that you post about things you learn and try to engage your audience often. </p>
<p>Finding the balance between letting your personality show while also adding value via sharing your knowledge can be tricky, but your followers will appreciate it!</p>
<h2 id="heading-in-summary">In Summary</h2>
<p>Whether you are new to the field and are looking for your first job, or you are an experienced developer looking for a new challenge, I hope these insights help. </p>
<p>The job hunt can be a daunting, exhausting process. But remember, it is a marathon, not a race. You got this. Consistency is key. Every rejection is an opportunity to improve your skills for the job you were meant for. </p>
<p>If you are struggling with any aspect of the job hunt, please feel free to <a target="_blank" href="mailto:martin@hey.com">send me an email</a>.</p>
<p>If you enjoyed this blog, please keep a lookout for the next entry in the <em>Interview Insights</em> series. My next article will be focused on preparing for technical interviews, look for that in 2 weeks. Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ System Design Interview Question Handbook – Concepts You Should Know ]]>
                </title>
                <description>
                    <![CDATA[ You may have heard the terms "Architecture" or "System Design." These come up a lot during developer job interviews – especially at big tech companies. I wrote this in-depth guide when preparing for my FAANG software engineering interviews. It covers... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/systems-design-for-interviews/</link>
                <guid isPermaLink="false">66d461da57503cc72873deee</guid>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                    <category>
                        <![CDATA[ systems-engineering ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zubin Pratap ]]>
                </dc:creator>
                <pubDate>Wed, 01 Apr 2020 15:21:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/System-Design-Book-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You may have heard the terms "Architecture" or "System Design." These come up a lot during developer job interviews – especially at big tech companies.</p>
<p>I wrote this in-depth guide when preparing for my FAANG software engineering interviews. It covers the essential software system design concepts you need to reason your way through distributed systems, and it helped me get into Google as an engineer, after more than 15 years of being a corporate lawyer.</p>
<p>This is not an exhaustive treatment, since System Design is a vast topic. But if you're a junior or mid-level developer, this should give you a strong foundation.</p>
<p>From there, you can dig deeper with other resources. I've listed some of my favourite resources at the very bottom of this article.</p>
<p>I've broken this guide into bite-sized chunks by topic and so I recommend you bookmark it. I've found <a target="_blank" href="https://www.freecodecamp.org/news/use-spaced-repetition-with-anki-to-learn-to-code-faster-7c334d448c3c/">spaced learning and repetition</a> to be incredibly valuable tools to learn and retain information. And I've designed this guide to be chunked down into pieces that are easy to do spaced repetition with.</p>
<ol>
<li><p><a class="post-section-overview" href="#heading-section-1-networks-and-protocols">Section 1: Networks &amp; Protocols (IP, DNS, HTTP, TCP etc)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-2-storage-latency-amp-throughput">Section 2: Storage, Latency &amp; Throughput</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-3-system-availability">Section 3: Availability</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-4-caching">Section 4: Caching</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-5-proxies">Section 5: Proxies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-6-load-balancing">Section 6: Load Balancing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-7-consistent-hashing">Section 7: Consistent Hashing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-8-databases">Section 8: Databases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-9-leader-election">Section 9: Leader Election</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-10-polling-streaming-sockets">Section 10: Polling, Streaming, Sockets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-11-endpoint-protection">Section 11: Endpoint Protection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-12-messaging-amp-pub-sub">Section 12: Messages &amp; Pub-Sub</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-13-smaller-essentials">Section 13: Smaller Essentials</a></p>
</li>
</ol>
<p>Let's get started!</p>
<h2 id="heading-section-1-networks-and-protocols">Section 1: Networks and Protocols</h2>
<p>"Protocols" is a fancy word that has a meaning in English totally independent of computer science. It means a system of rules and regulations that govern something. A kind of "official procedure" or "official way something must be done".</p>
<p>For people to connect to machines and code that communicate with each other, they need a network over which such communication can take place. But the communication also needs some rules, structure, and agreed-upon procedures.</p>
<p>Thus, network protocols are protocols that govern how machines and software communicate over a given network. An example of a network is our beloved world wide web.</p>
<p>You may have heard of the most common network protocols of the internet era - things like HTTP, TCP/IP etc. Let's break them down into basics.</p>
<h3 id="heading-ip-internet-protocolhttpsenwikipediaorgwikiinternetprotocol">IP - <a target="_blank" href="https://en.wikipedia.org/wiki/Internet_Protocol">Internet Protocol</a></h3>
<p>Think of this as the fundamental layer of protocols. It is the basic protocol that instructs us on how almost all communication across internet networks must be implemented.</p>
<p>Messages over IP are often communicated in "packets", which are small bundles of information (2^16 bytes). Each packet has an <a target="_blank" href="https://en.wikipedia.org/wiki/IPv4#Packet_structure">essential structure</a> made up of two components: the Header and the Data.</p>
<p>The header contains "meta" data about the packet and its data. This metadata includes information such as the IP address of the source (where the packet comes from) and the destination IP address (destination of the packet). Clearly, this is fundamental to being able to send information from one point to another - you need the "from" and "to" addresses.</p>
<p>And an <a target="_blank" href="https://en.wikipedia.org/wiki/IP_address">IP Address</a> is a numeric label assigned to each device connected to a <a target="_blank" href="https://en.wikipedia.org/wiki/Computer_network">computer network</a> that uses the Internet Protocol for communication. There are public and private IP addresses, and there are currently two versions. The new version is called IPv6 and is increasingly being adopted because IPv4 is running out of numerical addresses.</p>
<p>The other protocols we will consider in this post are built on top of IP, just like your favorite software language has libraries and frameworks built on top of it.</p>
<h3 id="heading-tcp-transmission-control-protocolhttpsenwikipediaorgwikitransmissioncontrolprotocol">TCP - <a target="_blank" href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">Transmission Control Protocol</a></h3>
<p>TCP is a utility built on top of IP. As you may know from reading my posts, I firmly believe you need to understand <em>why</em> something was invented in order to truly understand <em>what</em> it does.</p>
<p>TCP was created to solve a problem with IP. Data over IP is typically sent in multiple packets because each packet is fairly small (2^16 bytes). Multiple packets can result in (A) lost or dropped packets and (B) disordered packets, thus corrupting the transmitted data. TCP solves both of these by guaranteeing <em>transmission</em> of packets in an <em>ordered</em> way.</p>
<p>Being built on top of IP, the packet has a header called the TCP header in addition to the IP header. This TCP header contains information about the ordering of packets, and the number of packets and so on. This ensures that the data is reliably received at the other end. It is generally referred to as TCP/IP because it is built on top of IP.</p>
<p>TCP needs to establish a connection between source and destination before it transmits the packets, and it does this via a "handshake". This connection itself is established using packets where the source informs the destination that it wants to open a connection, and the destination says OK, and then a connection is opened.</p>
<p>This, in effect, is what happens when a server "listens" at a port - just before it starts to listen there is a handshake, and then the connection is opened (listening starts). Similarly, one sends the other a message that it is about to close the connection, and that ends the connection.</p>
<h3 id="heading-http-hyper-text-transfer-protocolhttpsenwikipediaorgwikihypertexttransferprotocol">HTTP - <a target="_blank" href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">Hyper Text Transfer Protocol</a></h3>
<p>HTTP is a protocol that is an abstraction built on top of TCP/IP. It introduces a very important pattern called the request-response pattern, specifically for client-server interactions.</p>
<p>A client is simply a machine or system that requests information, and a server is the machine or system that responds with information. A browser is a client, and a web-server is a server. When a server requests data from another server then the first server is also a client, and the second server is the server (I know, tautologies).</p>
<p>So this request-response cycle has its own rules under HTTP and this standardizes how information is transmitted across the internet.</p>
<p>At this level of abstraction we typically don't need to worry too much about IP and TCP. However, in HTTP, requests and responses have headers and bodies too, and these contain data that can be set by the developer.</p>
<p>HTTP requests and responses can be thought of as messages with key-value pairs, very similar to objects in JavaScript and dictionaries in Python, but not the same.</p>
<p>Below is an illustration of the content, and key-value pairs in HTTP request and response messages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-44.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>source:</em> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages"><em>https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages</em></a></p>
<p>HTTP also comes with some "verbs" or "methods" which are commands that give you an idea of what sort of operation is intended to be performed. For example, the common HTTP methods are "GET", "POST", "PUT", "DELETE" and "PATCH", but there are more. In the above picture, look for the HTTP verb in the start line.</p>
<h2 id="heading-section-2-storage-latency-amp-throughput">Section 2: Storage, Latency &amp; Throughput</h2>
<h3 id="heading-storage">Storage</h3>
<p>Storage is about holding information. Any app, system, or service that you program will need to store and retrieve data, and those are the two fundamental purposes of storage.</p>
<p>But it's not just about storing data – it's also about fetching it. We use a database to achieve this. A database is a software layer that helps us store and retrieve data.</p>
<p>These two primary types of operations, storing and retrieving, are also variously called 'set, get', 'store, fetch', 'write, read' and so on. To interact with storage, you will need to go through the database, which acts as an intermediary for you to conduct these fundamental operations.</p>
<p>The word "storage" can sometimes fool us into thinking about it in physical terms. If I "store" my bike in the shed, I can expect it to be there when I next open the shed.</p>
<p>But that doesn't always happen in the computing world. Storage can broadly be of two types: "Memory" storage and "Disk" storage.</p>
<p>Of these two, the disk storage tends to be the more robust and "permanent" (not truly permanent, so we often use the word "persistent" storage instead). Disk storage is persistent storage. This means that when you save something to Disk, and turn the power off, or restart your server, that data will "persist". It won't be lost.</p>
<p>However, if you leave data in "Memory" then that usually gets wiped away when you shut down or restart, or otherwise lose power.</p>
<p>The computer you use everyday has both these storage types. Your hard disk is<br>"persistent" Disk storage, and your RAM is transient Memory storage.</p>
<p>On servers, if the data you're keeping track of is only useful during a session of that server, then it makes sense to keep it in Memory. This is much faster and less expensive than writing things to a persistent database.</p>
<p>For example, a single session may mean when a user is logged in and using your site. After they log out, you may not need to hold on to bits of data that you collected during the session.</p>
<p>But whatever you do want to hold on to (like shopping cart history) you will put in persistent Disk storage. That way you can access that data the next time the user logs in, and they will have a seamless experience.</p>
<p>Ok, so this seems quite simple and basic, and it's meant to be. This is a primer. Storage can get very complex. If you take a look at the range of storage products and solutions your head will spin.</p>
<p>This is because different use-cases require different types of storage. They key to choosing the right storage types for your system depends on a lot of factors and the needs of your application, and how users interact with it. Other factors include:</p>
<ul>
<li><p>the shape (structure) of your data, or</p>
</li>
<li><p>what sort of availability it needs (what level of downtime is OK for your storage), or</p>
</li>
<li><p>scalability (how fast do you need to read and write data, and will these reads and writes happen concurrently (simultaneously) or sequentially) etc, or</p>
</li>
<li><p>consistency - if you protect against downtime using distributed storage, then how consistent is the data across your stores?</p>
</li>
</ul>
<p>These questions and the conclusions require you to consider your trade-offs carefully. Is consistency more important than speed? Do you need the database to service millions of operations per minute or only for nightly updates? I will be dealing with these concepts in sections later, so don't worry if you've no idea what they are.</p>
<h3 id="heading-latency">Latency</h3>
<p>"Latency" and "Throughput" are terms you're going to hear a lot of as you start to get more experienced with designing systems to support the front end of your application. They are very fundamental to the experience and performance of your application and the system as a whole. There is often a tendency to use these terms in a broader sense than intended, or out of context, but let's fix that.</p>
<p><strong>Latency</strong> is simply the measure of a duration. What duration? The duration for an action to complete something or produce a result. For example: for data to move from one place in the system to another. You may think of it as a lag, or just simply the time taken to complete an operation.</p>
<p>The most commonly understood latency is the "round trip" network request - how long does it take for your front end website (client) to send a query to your server, and get a response back from the server.</p>
<p>When you're loading a site, you want this to be as fast and as smooth as possible. In other words you want <em>low</em> latency. Fast lookups means low latency. So finding a value in an array of elements is slower (higher latency, because you need to iterate over each element in the array to find the one you want) than finding a value in a hash-table (lower latency, because you simply look up the data in "constant" time , by using the key. No iteration needed.).</p>
<p>Similarly, reading from memory is much faster than reading from a disk (read more <a target="_blank" href="https://stackoverflow.com/questions/1371400/how-much-faster-is-the-memory-usually-than-the-disk">here</a><em>).</em> But both have latency, and your needs will determine which type of storage you pick for which data.</p>
<p>In that sense, latency is the inverse of speed. You want higher speeds, and you want lower latency. Speed (especially on network calls like via HTTP) is determined also by the distance. So, <a target="_blank" href="https://wondernetwork.com/pings/London">latency from London to another city</a>, will be impacted by the distance from London.</p>
<p>As you can imagine, you want to design a system to avoid pinging distant servers, but then storing things in memory may not be feasible for your system. These are the tradeoffs that make system design complex, challenging and extremely interesting!</p>
<p>For example, websites that show news articles may prefer uptime and availability over loading speed, whereas online multiplayer games may require availability <em>and</em> super low latency. These requirements will determine the design and investment in infrastructure to support the system's special requirements.</p>
<h3 id="heading-throughput">Throughput</h3>
<p>This can be understood as the maximum capacity of a machine or system. It's often used in factories to calculate how much work an assembly line can do in an hour or a day, or some other unit of time measurement.</p>
<p>For example an assembly line can assemble 20 cars per hour, which is its throughput. In computing it would be the amount of data that can be passed around in a unit of time. So a 512 Mbps internet connection is a measure of throughput - 512 Mb (megabits) per second.</p>
<p>Now imagine freeCodeCamp's web-server. If it receives 1 million requests per second, and can serve only 800,000 requests, then its throughput is 800,000 per second. You may end up measuring the throughput in terms of bits instead of requests, so it would be N bits per second.</p>
<p>In this example, there is a <em>bottleneck</em> because the server cannot handle more than N bits a second, but the requests are more than that. A bottleneck is therefore the constraint on a system. A system is only as fast as its <em>slowest bottleneck.</em></p>
<p>If one server can handle 100 bits per second, and another can handle 120 bits per second and a third can handle only 50, then the overall system will be operating at 50bps because that is the constraint - it holds up the speed of the other servers in a given system.</p>
<p>So increasing throughput anywhere other than the bottleneck may be a waste - you may want to just increase <em>throughput</em> at the <em>lowest bottleneck</em> first.</p>
<p>You can increase throughput by buying more hardware (horizontal scaling) or increasing the capacity and performance of your existing hardware (vertical scaling) or a few other ways.</p>
<p>Increasing throughput may sometimes be a short term solution, and so a good systems designer will think through the best ways to scale the throughput of a given system including by splitting up requests (or any other form of "load"), and distributing them across other resources etc. The key point to remember is what throughput is, what a constraint or bottleneck is, and how it impacts a system.</p>
<p>Fixing latency and throughput are not isolated, universal solutions by themselves, nor are they correlated to each other. They have impacts and considerations across the system, so it's important to understand the system as a whole, and the nature of the demands that will be placed on the system over time.</p>
<h2 id="heading-section-3-system-availability">Section 3: System Availability</h2>
<p>Software engineers aim to build systems that are reliable. A reliable system is one that consistently satisfies a user's needs, whenever that user seeks to have that need satisfied. A key component of that reliability is Availability.</p>
<p>It's helpful to think of availability as the resiliency of a system. If a system is robust enough to handle failures in the network, database, servers etc, then it can generally be considered to be a fault-tolerant system - which makes it an available system.</p>
<p>Of course, a system is a sum of its parts in many senses, and each part needs to be <a target="_blank" href="https://en.wikipedia.org/wiki/High_availability">highly available</a> if availability is relevant to the end user experience of the site or app.</p>
<h3 id="heading-quantifying-availability">Quantifying Availability</h3>
<p>To quantify the availability of a system, we calculate the percentage of time that the system's primary functionality and operations are available (the uptime) in a given window of time.</p>
<p>The most business-critical systems would need to have a near-perfect availability. Systems that support highly variable demands and loads with sharp peaks and troughs may be able to get away with slightly lower availability during off-peak times.</p>
<p>It all depends on the use and nature of the system. But in general, even things that have low, but consistent demands or an implied guarantee that the system is "on-demand" would need to have high availability.</p>
<p>Think of a site where you backup your pictures. You don't always need to access and retrieve data from this - it's mainly for you to store things in. You would still expect it to always be available any time you login to download even just a single picture.</p>
<p>A different kind of availability can be understood in the context of the massive e-commerce shopping days like Black Friday or Cyber Monday sales. On these particular days demand will skyrocket and millions will try to access the deals simultaneously. That would require an extremely reliable and high-availability system design to support those loads.</p>
<p>A commercial reason for high availability is simply that any downtime on the site will result in the site losing money. Also, it could be really bad for reputation, for example, where the service is a service used by <em>other</em> businesses to offer services. If AWS S3 goes down, a lot of companies will suffer, including Netflix, and that is <em>not good</em>.</p>
<p>So uptimes are extremely important for success. It is worth remembering that commercial availability numbers are calculated based on annual availability, so a downtime of 0.1% (i.e. availability of 99.9%) is <a target="_blank" href="https://en.wikipedia.org/wiki/High_availability">8.77 hours a year</a>!</p>
<p>Hence, uptimes are extremely high sounding. It is common to see things like 99.99% uptime (52.6 minutes of downtime per year). Which is why it is now common to refer to uptimes in terms of "nines" - <a target="_blank" href="https://en.wikipedia.org/wiki/High_availability#%22Nines%22">the number of nines</a> in the uptime assurance.</p>
<p>In today's world that is unacceptable for large-scale or mission critical services. Which is why these days "five nines" is considered the ideal availability standard because that translates to a little over 5 minutes of downtime <em>per year</em>.</p>
<h3 id="heading-slas">SLAs</h3>
<p>In order to make online services competitive and meet the market's expectations, online service providers typically offer Service Level Agreements/Assurances. These are a set of guaranteed service level metrics. 99.999% uptime is one such metric and is often offered as part of premium subscriptions.</p>
<p>In the case of database and cloud service providers this can be offered even on the trial or free tiers if a customer's core use for that product justifies the expectation of such a metric.</p>
<p>In many cases failing to meet the SLA will give the customer a right to credits or some other form of compensation for the provider's failure to meet that assurance. Here, by way of example, is <a target="_blank" href="https://cloud.google.com/maps-platform/terms/sla">Google's SLA for the Maps API.</a></p>
<p>SLAs are therefore a critical part of the overall commercial and technical consideration when designing a system. It is especially important to consider whether availability is in fact a key requirement for a part of a system, and which parts require high availability.</p>
<h3 id="heading-designing-ha">Designing HA</h3>
<p>When designing a high availability (HA) system, then, you need to reduce or eliminate "single points of failure". A single point of failure is an element in the system that is the <em>sole</em> element that can produce that undesirable loss of availability.</p>
<p>You eliminate single points of failure by designing 'redundancy' into the system. Redundancy is basically making 1 or more alternatives (i.e. backups) to the element that is critical for high availability.</p>
<p>So if your app needs users to be authenticated to use it, and there is only one authentication service and back end, and that fails, then, because that is the single point of failure, your system is no longer usable. By having two or more services that can handle authentication, you have added redundancy and eliminated (or reduced) single points of failure.</p>
<p>Therefore, you need to understand and de-compose your system into all its parts. Map out which ones are likely to cause single points of failure, which ones are not tolerant of such failure, and which parts can tolerate them. Because engineering HA requires tradeoffs and some of these tradeoffs may be expensive in terms of time, money and resources.</p>
<h2 id="heading-section-4-caching">Section 4: Caching</h2>
<p>Caching! This is a very fundamental and easy-to-understand technique to speed up performance in a system. Thus caching helps to reduce <a class="post-section-overview" href="#storage-latency-throughput">"latency"</a> in a system.</p>
<p>In our daily lives, we use caching as a matter of common-sense (most of the time...). If we live next door to a supermarket, we still want to buy and store some basics in our fridge and our food cupboard. This is caching. We could always step out, go next door, and buy these things every time we want food – but if its in the pantry or fridge, we reduce the time it takes to make our food. That's caching.</p>
<h3 id="heading-common-scenarios-for-caching">Common Scenarios for Caching</h3>
<p>Similarly, in software terms, if we end up relying on certain pieces of data often, we may want to cache that data so that our app performs faster.</p>
<p>This is often true when it's faster to retrieve data from Memory rather than <a class="post-section-overview" href="#storage-latency-throughput">disk</a> because of the latency in making network requests. In fact many websites are cached (especially if content doesn't change frequently) in <a target="_blank" href="https://www.cloudflare.com/learning/cdn/what-is-caching/">CDNs</a> so that it can be served to the end user much faster, and it reduces load on the backend servers.</p>
<p>Another context in which caching helps could be where your backend has to do some computationally intensive and time consuming work. Caching previous results that converts your lookup time from a linear O(N) time to constant O(1) time could be very advantageous.</p>
<p>Likewise, if your server has to make multiple network requests and API calls in order to compose the data that gets sent back to the requester, then caching data could reduce the number of network calls, and thus the latency.</p>
<p>If your system has a client (front end), and a server and databases (backend) then caching can be inserted on the client (e.g. browser storage), between the client and the server (e.g. CDNs), or on the server itself. This would reduce over-the-network calls to the database.</p>
<p>So caching can occur at multiple points or levels in the system, including at the hardware (CPU) level.</p>
<h3 id="heading-handling-stale-data">Handling Stale Data</h3>
<p>You may have noticed that the above examples are implicitly handy for "read" operations. Write operations are not that different, in main principles, with the following added considerations:</p>
<ul>
<li><p>write operations require keeping the cache and your database in sync</p>
</li>
<li><p>this may increase complexity because there are more operations to perform, and new considerations around handling un-synced or "stale" data need to be carefully analyzed</p>
</li>
<li><p>new design principles may need to be implemented to handle that syncing - should it be done synchronously, or asynchronously? If async, then at what intervals? Where does data get served from in the mean time? How often does the cache need to be refreshed, etc...</p>
</li>
<li><p>data "eviction" or turnover and refreshes of data, to keep cached data fresh and up-to-date. These include techniques like <a target="_blank" href="https://en.wikipedia.org/wiki/Cache_replacement_policies#Last_in_first_out_(LIFO)_or_First_in_last_out_(FILO)">LIFO</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Cache_replacement_policies#First_in_first_out_(FIFO)">FIFO</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)">LRU</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Cache_replacement_policies#Least-frequently_used_(LFU)">LFU</a>.</p>
</li>
</ul>
<p>So let's end with some high-level, and non-binding conclusions. Generally, caching works best when used to store static or infrequently changing data, and when the sources of change are likely to be single operations rather than user-generated operations.</p>
<p>Where consistency and freshness in data is critical, caching may not be an optimal solution, unless there is another element in the system that efficiently refreshes the caches at intervals that do not adversely impact the purpose and user experience of the application.</p>
<h2 id="heading-section-5-proxies">Section 5: Proxies</h2>
<p>Proxy. What? Many of us have heard of proxy servers. We may have seen configuration options on some of our PC or Mac software that talk about adding and configuring proxy servers, or accessing "via a proxy".</p>
<p>So let's understand that relatively simple, widely used and important piece of tech. This is a word that exists in the English language completely independent of computer science, so let's start with that <a target="_blank" href="https://www.merriam-webster.com/dictionary/proxy">definition</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-08-at-12.57.03-pm.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://www.merriam-webster.com/dictionary/proxy"><em>https://www.merriam-webster.com/dictionary/proxy</em></a></p>
<p>Now you can eject most of that out of your mind, and hold on to one key word: "substitute".</p>
<p>In computing, a proxy is typically a server, and it is a server that acts as a middleman between a client and another server. It literally is a bit of code that sits between client and server. That's the crux of proxies.</p>
<p>In case you need a refresher, or aren't sure of the definitions of client and server, a "client" is a process (code) or machine that requests data from another process or machine (the "server"). The browser is a client when it requests data from a backend server.</p>
<p>The server serves the client, but can also be a client - when it retrieves data from a database. Then the database is the server, the server is the client (of the database) and <em>also</em> a server for the front-end client (browser).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-22.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://teoriadeisegnali.it/appint/html/altro/bgnet/clientserver.html#figure2"><em>https://teoriadeisegnali.it/appint/html/altro/bgnet/clientserver.html#figure2</em></a></p>
<p>As you can see from the above, the client-server relationship is bi-directional. So one thing can be both the client and server. If there was a middleman server that received requests, then sent them to another service, then forwards the response it got from that other service back to the originator client, that would be a proxy server.</p>
<p>Going forward we will refer to clients as clients, servers as servers and proxies as the thing between them.</p>
<p>So when a client sends a request to a server via the proxy, the proxy may sometimes mask the identity of the client - to the server, the IP address that comes through in the request may be the proxy and not the originating client.</p>
<p>For those of you who access sites or download things that otherwise are restricted (from the torrent network for example, or sites banned in your country), you may recognize this pattern - it's the principle on which VPNs are built.</p>
<p>Before we move a bit deeper, I want to call something out - when generally used, the term proxy refers to a "forward" proxy. A forward proxy is one where the proxy acts on behalf of (substitute for) the client in the interaction between client and server.</p>
<p>This is distinguished from a reverse proxy - where the proxy acts on behalf of a server. On a diagram it would look the same - the proxy sits between the client and the server, and the data flows are the same client &lt;-&gt; proxy &lt;-&gt; server.</p>
<p>The key difference is that a reverse proxy is designed substitute for the server. Often clients won't even know that the network request got routed through a proxy and the proxy passed it on to the intended server (and did the same thing with the server's response).</p>
<p>So, in a forward proxy, the server won't know that the client's request and its response are traveling through a proxy, and in a reverse proxy the client won't know that the request and response are routed through a proxy.</p>
<p>Proxies feel kinda sneaky :)</p>
<p>But in systems design, especially for complex systems, proxies are useful and reverse proxies are particularly useful. Your reverse proxy can be delegated a lot of tasks that you don't want your main server handling - it can be a gatekeeper, a screener, a load-balancer and an all around assistant.</p>
<p>So proxies can be useful but you may not be sure why. Again, if you've read my other stuff you'd know that I firmly believe that you can understand things properly only when you know <em>why</em> they exist - knowing <em>what</em> they do is not enough.</p>
<h2 id="heading-section-6-load-balancing">Section 6: Load Balancing</h2>
<p>If you think about the two words, load and balance, you will start to get an intuition as to what this does in the world of computing. When a server simultaneously receives a lot of requests, it can slow down (throughput reduces, latency rises). After a point it may even fail (no availability).</p>
<p>You can give the server more muscle power (vertical scaling) or you can add more servers (horizontal scaling). But now you got to work out how the income requests get distributed to the various servers - which requests get routed to which servers and how to ensure they don't get overloaded too? In other words, how do you balance and allocate the request load?</p>
<p>Enter load balancers. Since this article is an introduction to principles and concepts, they are, of necessity, very simplified explanations. A load balancer's job is to sit between the client and server (but there are other places it can be inserted) and work out how to distribute incoming request loads across multiple servers, so that the end user (client's) experience is consistently fast, smooth and reliable.</p>
<p>So load balancers are like traffic managers who direct traffic. And they do this to maintain <a class="post-section-overview" href="#system-availability">availability</a> and <a class="post-section-overview" href="#storage-latency-throughput">throughput</a>.</p>
<p>When understanding where a load balancer is inserted in the system's architecture, you can see that load balancers can be thought of as <a class="post-section-overview" href="#proxies">reverse proxies</a>. But a load balancer can be inserted in other places too - between other exchanges - for example, between your server and your database.</p>
<h3 id="heading-the-balancing-act-server-selection-strategies">The Balancing Act - Server Selection Strategies</h3>
<p>So how does the load balancer decide how to route and allocate request traffic? To start with, every time you add a server, you need to let your load balancer know that there is one more candidate for it to route traffic to.</p>
<p>If you remove a server, the load balancer needs to know that too. The configuration ensures that the load balancer knows how many servers it has in its go-to list and which ones are available. It is even possible for the load balancer to be kept informed on each server's load levels, status, availability, current task and so on.</p>
<p>Once the load balancer is configured to know what servers it can redirect to, we need to work out the best routing strategy to ensure there is proper distribution amongst the available servers.</p>
<p>A naive approach to this is for the load balancer to just randomly pick a server and direct each incoming request that way. But as you can imagine, randomness can cause problems and "unbalanced" allocations where some servers get more loaded than others, and that could affect performance of the overall system negatively.</p>
<h3 id="heading-round-robin-and-weighted-round-robin">Round Robin and Weighted Round Robin</h3>
<p>Another method that can be intuitively understood is called "round robin". This is the way many humans process lists that loop. You start at the first item in the list, move down in sequence, and when you're done with the last item you loop back up to the top and start working down the list again.</p>
<p>The load balancer can do this too, by just looping through available servers in a fixed sequence. This way the load is pretty evenly distributed across your servers in a simple-to-understand and predictable pattern.</p>
<p>You can get a little more "fancy" with the round robin by "weighting" some services over others. In the normal, standard round robin, each server is given equal weight (let's say all are given a weighting of 1). But when you differently weight servers, then you can have some servers with a lower weighting (say 0.5, if they're less powerful), and others can be higher like 0.7 or 0.9 or even 1.</p>
<p>Then the total traffic will be split up in proportion to those weights and allocated accordingly to the servers that have power proportionate to the volume of requests.</p>
<h3 id="heading-load-based-server-selection">Load-based server selection</h3>
<p>More sophisticated load balancers can work out the current capacity, performance, and loads of the servers in their go-to list and allocate dynamically according to current loads and calculations as to which will have the highest throughput, lowest latency etc. It would do this by monitoring the performance of each server and deciding which ones can and cannot handle the new requests.</p>
<h3 id="heading-ip-hashing-based-selection">IP Hashing based selection</h3>
<p>You can configure your load balancer to <a target="_blank" href="https://www.cs.cmu.edu/~adamchik/15-121/lectures/Hashing/hashing.html">hash</a> the IP address of incoming requests, and use the hash value to determine which server to direct the request too. If I had 5 servers available, then the hash function would be designed to return one of five hash values, so one of the servers definitely gets nominated to process the request.</p>
<p>IP hash based routing can be very useful where you want requests from a certain country or region to get data from a server that is best suited to address the needs from within that region, or where your servers cache requests so that they can be processed fast.</p>
<p>In the latter scenario, you want to ensure that the request goes to a server that has previously cached the same request, as this will improve speed and performance in processing and responding to that request.</p>
<p>If your servers each maintain independent caches and your load balancer does not consistently send identical requests to the same server, you will end up with servers re-doing work that has already been done in as previous request to another server, and you lose the optimization that goes with caching data.</p>
<h3 id="heading-path-or-service-based-selection">Path or Service based selection</h3>
<p>You can also get the load balancer to route requests based on their "path" or function or service that is being provided. For example if you're buying flowers from an online florist, requests to load the "Bouquets on Special" may be sent to one server and credit card payments may be sent to another server.</p>
<p>If only one in twenty visitors actually bought flowers, then you could have a smaller server processing the payments and a bigger one handling all the browsing traffic.</p>
<h3 id="heading-mixed-bag">Mixed Bag</h3>
<p>And as with all things, you can get to higher and more detailed levels of complexity. You can have multiple load balancers that each have different server selection strategies! And if yours is a very large and highly trafficked system, then you may need <em>load balancers for load balancers...</em></p>
<p>Ultimately, you add pieces to the system until your performance is tuned to your needs (your needs may look flat, or slow upwards mildly over time, or be prone to spikes!).</p>
<p>We've talked about VPNs (for forward proxies) and load-balancing (for reverse proxies), but there are more examples <a target="_blank" href="https://www.quora.com/What-are-the-different-uses-of-proxy-servers">here</a>.</p>
<h2 id="heading-section-7-consistent-hashing">Section 7: Consistent Hashing</h2>
<p>One of the slightly more tricky concepts to understand is hashing in the context of load balancing. So it gets its own section.</p>
<p>In order to understand this, please first understand <a target="_blank" href="https://www.cs.cmu.edu/~guna/15-123S11/Lectures/Lecture17.pdf">how hashing works at a conceptual level</a>. The TL;DR is that hashing converts an input into a fixed-size value, often an integer value (the hash).</p>
<p>One of the key principles for a good hashing algorithm or function is that the function must be <a target="_blank" href="https://en.wikipedia.org/wiki/Hash_function#Deterministic">deterministic</a>, which is a fancy way for saying that identical inputs will generate identical outputs when passed into the function. So, deterministic means - if I pass in the string "Code" (case sensitive) and the function generates a hash of 11002, then every time I pass in "Code" it must generate "11002" as an integer. And if I pass in "code" it will generate a different number (consistently).</p>
<p>Sometimes the hashing function can generate the same hash for more than one input - this is not the end of the world and there are ways to deal with it. In fact it becomes more likely the more the range of unique inputs are. But when more than one input deterministically generates the same output, it's called a "collision".</p>
<p>With this in firmly in mind, let's apply it to routing and directed requests to servers. Let's say you have 5 servers to allocate loads across. An easy to understand method would be to hash incoming requests (maybe by IP address, or some client detail), and then generate hashes for each request. Then you apply the modulo operator to that hash, where the right operand is the number of servers.</p>
<p>For example, this is what your load balancers' pseudo code could look like:</p>
<pre><code class="lang-javascript">
request#<span class="hljs-number">1</span> =&gt; hashes to <span class="hljs-number">34</span>
request#<span class="hljs-number">2</span> =&gt; hashes to <span class="hljs-number">23</span>
request#<span class="hljs-number">3</span> =&gt; hashes to <span class="hljs-number">30</span>
request#<span class="hljs-number">4</span> =&gt; hashes to <span class="hljs-number">14</span>

<span class="hljs-comment">// You have 5 servers =&gt; [Server A, Server B ,Server C ,Server D ,Server E]</span>

<span class="hljs-comment">// so modulo 5 for each request...</span>

request#<span class="hljs-number">1</span> =&gt; hashes to <span class="hljs-number">34</span> =&gt; <span class="hljs-number">34</span> % <span class="hljs-number">5</span> = <span class="hljs-number">4</span> =&gt; send <span class="hljs-built_in">this</span> request to servers[<span class="hljs-number">4</span>] =&gt; Server E

request#<span class="hljs-number">2</span> =&gt; hashes to <span class="hljs-number">23</span> =&gt; <span class="hljs-number">23</span> % <span class="hljs-number">5</span> = <span class="hljs-number">3</span> =&gt; send <span class="hljs-built_in">this</span> request to servers[<span class="hljs-number">3</span>] =&gt; Server D

request#<span class="hljs-number">3</span> =&gt; hashes to <span class="hljs-number">30</span> =&gt; <span class="hljs-number">30</span> % <span class="hljs-number">5</span> = <span class="hljs-number">0</span> =&gt; send <span class="hljs-built_in">this</span> request to  servers[<span class="hljs-number">0</span>] =&gt; Server A

request#<span class="hljs-number">4</span> =&gt; hashes to <span class="hljs-number">14</span> =&gt; <span class="hljs-number">14</span> % <span class="hljs-number">5</span> = <span class="hljs-number">4</span> =&gt; send <span class="hljs-built_in">this</span> request to servers[<span class="hljs-number">4</span>] =&gt; Server E
</code></pre>
<p>As you can see, the hashing function generates a spread of possible values, and when the modulo operator is applied it brings out a smaller range of numbers that map to the server number.</p>
<p>You will definitely get different requests that map to the same server, and that's fine, as long as there is "<a target="_blank" href="https://en.wikipedia.org/wiki/Hash_function#Uniformity">uniformity</a>" in the overall allocation to all the servers.</p>
<h3 id="heading-adding-servers-and-handling-failing-servers">Adding Servers, and Handling Failing Servers</h3>
<p>So - what happens if one of the servers that we are sending traffic to dies? The hashing function (refer to the pseudo code snippet above) still thinks there are 5 servers, and the mod operator generates a range from 0-4. But we only have 4 servers now that one has failed, and we are still sending it traffic. Oops.</p>
<p>Inversely, we could add a sixth server but that would <em>never</em> get any traffic because our mod operator is 5, and it will never yield a number that would include the newly added 6th server. Double oops.</p>
<pre><code class="lang-plaintext">// Let's add a 6th server
servers =&gt; [Server A, Server B ,Server C ,Server D ,Server E, Server F]

// let's change the modulo operand to 6
request#1 =&gt; hashes to 34 =&gt; 34 % 6 = 4 =&gt; send this request to servers[4] =&gt; Server E

request#2 =&gt; hashes to 23 =&gt; 23 % 6 = 5 =&gt; send this request to servers[5] =&gt; Server F

request#3 =&gt; hashes to 30 =&gt; 30 % 6 = 0 =&gt; send this request to  servers[0] =&gt; Server A

request#4 =&gt; hashes to 14 =&gt; 14 % 6 = 2 =&gt; send this request to servers[2] =&gt; Server C
</code></pre>
<p>We note that the server number after applying the mod changes (though, in this example, <em>not</em> for request#1 and request#3 - but that is just because in this specific case the numbers worked out that way).</p>
<p>In effect, the result is that half the requests (could be more in other examples!) are now being routed to new servers altogether, and we lose the benefits of previously cached data on the servers.</p>
<p>For example, request#4 used to go to Server E, but now goes to Server C. All the cached data relating to request#4 sitting on Server E is of no use since the request is now going to Server C. You can calculate a similar problem for where one of your servers dies, but the mod function keeps sending it requests.</p>
<p>It sounds minor in this tiny system. But on a very large scale system this is a poor outcome. #SystemDesignFail.</p>
<p>So clearly, a simple hashing-to-allocate system does not scale or handle failures well.</p>
<h3 id="heading-a-popular-solution-consistent-hashing">A popular solution - consistent hashing</h3>
<p>Unfortunately this is the part where I feel word descriptions will not be enough. Consistent hashing is best understood visually. But the purpose of this post so far is to give you an intuition around the problem, what it is, why it arises, and what the shortcomings in a basic solution might be. Keep that firmly in mind.</p>
<p>The key problem with naive hashing, as we discussed, is that when (A) a server fails, traffic still gets routed to it, and (B) you add a new server, the allocations can get substantially changed, thus losing the benefits of previous caches.</p>
<p>There are two very important things to keep in mind when digging into consistent hashing:</p>
<ol>
<li><p>Consistent hashing <em>does not eliminate the problems</em>, especially B. But it does reduce the problems a lot. At first you might wonder what the big deal is in consistent hashing, as the underlying downside still exists - yes, but to a much smaller extent, and that itself is a valuable improvement in very large scale systems.</p>
</li>
<li><p>Consistent hashing applies a hash function to incoming requests <em>and the servers</em>. The resulting outputs therefore fall in a set range (continuum) of values. This detail is very important.</p>
</li>
</ol>
<p>Please keep these in mind as you watch the below recommended video that explains consistent hashing, as otherwise its benefits may not be obvious.</p>
<p>I strongly recommend this video as it embeds these principles without burdening you with too much detail.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tHEyzVbl4bg" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>If you're having a little trouble really understanding why this strategy is important in load balancing, I suggest you take a break, then return to the <a class="post-section-overview" href="#load-balancing">load balancing section</a> and then re-read this again. It's not uncommon for all this to feel very abstract unless you've directly encountered the problem in your work!</p>
<h2 id="heading-section-8-databases">Section 8: Databases</h2>
<p>We briefly <a class="post-section-overview" href="#storage-latency-throughput">considered</a> that there are different types of storage solutions (databases) designed to suit a number of different use-cases, and some are more specialized for certain tasks than others. At a very high level though, databases can be categorized into two types: Relational and Non-Relational.</p>
<h3 id="heading-relational-databases">Relational Databases</h3>
<p>A <a target="_blank" href="https://en.wikipedia.org/wiki/Relational_database"><strong>relational database</strong></a> is one that has strictly enforced relationships between things stored in the database. These relationships are typically made possible by requiring the database to represented each such thing (called the "entity") as a structured table - with zero or more rows ("records", "entries") and and one or more columns ("attributes, "fields").</p>
<p>By forcing such a structure on an entity, we can ensure that each item/entry/record has the right data to go with it. It makes for better consistency and the ability to make tight relationships between the entities.</p>
<p>You can see this structure in the table recording "Baby" (entity) data below. Each record ("entry) in the table has 4 fields, which represent data relating to that baby. This is a classic relational database structure (and a formalized entity structure is called a <a target="_blank" href="https://en.wikipedia.org/wiki/Database_schema">schema</a>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-46.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>source:</em> <a target="_blank" href="https://web.stanford.edu/class/cs101/table-1-data.html"><em>https://web.stanford.edu/class/cs101/table-1-data.html</em></a></p>
<p>So the key feature to understand about relational databases is that they are highly structured, and impose structure on all the entities. This structure in enforced by ensuring that data added to the table conforms to that structure. Adding a height field to the table when its schema doesn't allow for it will not be permitted.</p>
<p>Most relational databases support a database querying language called SQL - <a target="_blank" href="https://en.wikipedia.org/wiki/SQL">Structured Query Language</a>. This is a language specifically designed to interact with the contents of a structured (relational) database. The two concepts are quite tightly coupled, so much so that people often referred to a relational database as a "SQL database" (and sometimes pronounced as "sequel" database).</p>
<p>In general, it is considered that SQL (relational) databases support more complex queries (combining different fields and filters and conditions) than non-relational databases. The database itself handles these queries and sends back matching results.</p>
<p>Many people who are SQL database fans argue that without that function, you would have to fetch <em>all</em> the data and then have the server or the client load that data "<a class="post-section-overview" href="#storage-latency-throughput">in memory</a>" and apply the filtering conditions - which is OK for small sets of data but for a large, complex dataset, with millions of records and rows, that would badly affect performance. However, this is not always the case, as we will see when we learn about NoSQL databases.</p>
<p>A common and much-loved example of a relational database is the <a target="_blank" href="https://en.wikipedia.org/wiki/PostgreSQL">PostgreSQL</a> (often called "Postgres") database.</p>
<h3 id="heading-acid">ACID</h3>
<p>ACID transactions are a set of features that describe the transactions that a good relational database will support. <a target="_blank" href="https://en.wikipedia.org/wiki/ACID">ACID = "Atomic, Consistent, Isolation, Durable"</a>. A transaction is an interaction with a database, typically read or write operations.</p>
<p><strong>Atomicity</strong> requires that when a single transaction comprises of more than one operation, then the database must guarantee that if one operation fails the <em>entire</em> transaction (all operations) also fail. It's "all or nothing". That way if the transaction succeeds, then on completion you know that all the sub-operations completed successfully, and if an operation fails, then you know that all the operations that went with it failed.</p>
<p>For example if a single transaction involved reading from two tables and writing to three, then if any one of those individual operations fails the entire transaction fails. This means that none of those individual operations should complete. You would not want even 1 out of the 3 write transactions to work - that would "dirty" the data in your databases!</p>
<p><strong>Consistency</strong> requires that each transaction in a database is valid according to the database's defined rules, and when the database changes state (some information has changed), such change is valid and does not corrupt the data. Each transaction moves the database from one <em>valid</em> state to another <em>valid</em> state. Consistency can be thought of as the following: every "read" operation receives the most recent "write" operation results.</p>
<p><strong>Isolation</strong> means that you can "concurrently" (at the same time) run multiple transactions on a database, but the database will end up with a state that looks as though each operation had been run serially ( in a sequence, like a queue of operations). I personally think "Isolation" is not a very descriptive term for the concept, but I guess ACCD is less easy to say than ACID...</p>
<p><strong>Durability</strong> is the promise that once the data is stored in the database, it will remain so. It will be "<a class="post-section-overview" href="#heading-section-2-storage-latency-amp-throughput">persistent</a>" - stored on disk and not in "memory".</p>
<h3 id="heading-non-relational-databases">Non-relational databases</h3>
<p>In contrast, a <strong>non-relational database</strong> has a less rigid, or, put another way, a more flexible structure to its data. The data typically is presented as "key-value" pairs. A simple way of representing this would be as an array (list) of "key-value" pair objects, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// baby names</span>
[
    { 
        <span class="hljs-attr">name</span>: <span class="hljs-string">"Jacob"</span>,
        <span class="hljs-attr">rank</span>: ##,
        <span class="hljs-attr">gender</span>: <span class="hljs-string">"M"</span>,
        <span class="hljs-attr">year</span>: ####
    },
    { 
        <span class="hljs-attr">name</span>: <span class="hljs-string">"Isabella"</span>,
        <span class="hljs-attr">rank</span>: ##,
        <span class="hljs-attr">gender</span>: <span class="hljs-string">"F"</span>,
        <span class="hljs-attr">year</span>: ####
    },
    {
      <span class="hljs-comment">//...</span>
    },

    <span class="hljs-comment">// ...</span>
]
</code></pre>
<p>Non relational databases are also referred to as "NoSQL" databases, and offer benefits when you do not want or need to have consistently structured data.</p>
<p>Similar to the ACID properties, NoSQL database properties are sometimes referred to as BASE:</p>
<p><strong>Basically Available</strong> which states that the system guarantees availability</p>
<p><strong>Soft State</strong> means the state of the system may change over time, even without input</p>
<p><strong>Eventual Consistency</strong> states that the system will become consistent over a (very short) period of time unless other inputs are received.</p>
<p>Since, at their core, these databases hold data in a hash-table-like structure, they are extremely fast, simple and easy to use, and are perfect for use cases like caching, environment variables, configuration files and session state etc. This flexibility makes them perfect for using in memory (e.g. <a target="_blank" href="https://en.wikipedia.org/wiki/Memcached">Memcached</a>) and also in persistent storage (e.g. <a target="_blank" href="https://en.wikipedia.org/wiki/Amazon_DynamoDB">DynamoDb</a>).</p>
<p>There are other "JSON-like" databases called document databases like the well-loved <a target="_blank" href="https://www.mongodb.com/document-databases">MongoDb</a>, and at the core these are also "key-value" stores.</p>
<h3 id="heading-database-indexing">Database Indexing</h3>
<p>This is a complicated topic so I will simply skim the surface for the purpose of giving you a high level overview of what you need for systems design interviews.</p>
<p>Imagine a database table with 100 million rows. This table is used mainly to look up one or two values in each record. To retrieve the values for a specific row you would need to iterate over the table. If it's the very last record that would take a long time!</p>
<p>Indexing is a way of short cutting to the record that has matching values more efficiently than going through each row. Indexes are typically a data structure that is added to the database that is designed to facilitate fast searching of the database for those <em>specific</em> attributes (fields).</p>
<p>So if the census bureau has 120 million records with names and ages, and you most often need to retrieve lists of people belonging to an age group, then you would index that database on the age attribute.</p>
<p>Indexing is core to relational databases and is also widely offered on non-relational databases. The benefits of indexing are thus available in theory for both types of databases, and this is hugely beneficial to optimise lookup times.</p>
<h3 id="heading-replication-and-sharding">Replication and Sharding</h3>
<p>While these may sound like things out of a bio-terrorism movie, you're more likely to hear them everyday in the context of database scaling.</p>
<p>Replication means to duplicate (make copies of, replicate) your database. You may remember that when we discussed <a class="post-section-overview" href="#system-availability">availability</a>.</p>
<p>We had considered the benefits of having redundancy in a system to maintain high availability. Replication ensures redundancy in the database if one goes down. But it also raises the question of how to synchronize data across the replicas, since they're meant to have the same data. Replication on write and update operations to a database can happen synchronously (at the same time as the changes to the main database) or asynchronously .</p>
<p>The acceptable time interval between synchronising the main and a replica database really depends on your needs - if you really need state between the two databases to be consistent then the replication needs to be rapid. You also want to ensure that if the write operation to the replica fails, the write operation to the main database also fails (atomicity).</p>
<p>But what do you do when you've got so much data that simply replicating it may solve availability issues but does not solve throughput and latency issues (speed)?</p>
<p>At this point you may want to consider "chunking down" your data, into "shards". Some people also call this partitioning your data (which is different from partitioning your hard drive!).</p>
<p>Sharding data breaks your huge database into smaller databases. You can work out how you want to shard your data depending on its structure. It could be as simple as every 5 million rows are saved in a different shard, or go for other strategies that best fit your data, needs and locations served.</p>
<h2 id="heading-section-9-leader-election">Section 9: Leader Election</h2>
<p>Let's move back to servers again for a slightly more advanced topic. We already understand the principle of <a class="post-section-overview" href="#heading-section-3-system-availability">Availability</a>, and how redundancy is one way to increase availability. We have also walked through some practical considerations when handling the <a class="post-section-overview" href="#heading-section-6-load-balancing">routing of requests</a> to clusters of redundant servers.</p>
<p>But sometimes, with this kind of setup where multiple servers are doing much the same thing, there can arise situations where you need only one server to take the lead.</p>
<p>For example, you want to ensure that only one server is given the responsibility for updating some third party API because multiple updates from different servers could cause issues or run up costs on the third-party's side.</p>
<p>In this case you need to choose that primary server to delegate this update responsibility to. That process is called <a target="_blank" href="https://en.wikipedia.org/wiki/Leader_election">leader election</a>.</p>
<p>When multiple servers are in a cluster to provide redundancy, they could, amongst themselves, be configured to have one and only one leader. They would also detect when that leader server has failed, and appoint another one to take its place.</p>
<p>The principle is very simple, but the devil is in the details. The really tricky part is ensuring that the servers are "in sync" in terms of their data, state and operations.</p>
<p>There is always the risk that certain outages could result in one or two servers being disconnected from the others, for example. In that case, engineers end up using some of the underlying ideas that are used in blockchain to derive consensus values for the cluster of servers.</p>
<p>In other words, a <a target="_blank" href="https://en.wikipedia.org/wiki/Consensus_algorithm">consensus algorithm</a> is used to give all the servers an "agreed on" value that they can all rely on in their logic when identifying which server is the leader.</p>
<p>Leader Election is commonly implemented with software like <a target="_blank" href="https://etcd.io/">etcd</a>, which is a store of key-value pairs that offers both high availability <em>and</em> strong consistency (which is valuable and an unusual combination) by using Leader Election itself and using a consensus algorithm.</p>
<p>So engineers can rely on etcd's own leader election architecture to produce leader election in their systems. This is done by storing in a service like etcd, a key-value pair that represents the current leader.</p>
<p>Since etcd is highly available <em>and</em> strongly consistent, that key-value pair can always be relied on by your system to contain the final "source of truth" server in your cluster is the current elected leader.</p>
<h2 id="heading-section-10-polling-streaming-sockets">Section 10: Polling, Streaming, Sockets</h2>
<p>In the modern age of continuous updates, push notifications, streaming content and real-time data, it is important to grasp the basic principles that underpin these technologies. To have data in your application updated regularly or instantly requires the use of one of the two following approaches.</p>
<h3 id="heading-polling">Polling</h3>
<p>This one is simple. If you look at the <a target="_blank" href="https://en.wikipedia.org/wiki/Polling_(computer_science)">wikipedia entry</a> you may find it a bit intense. So instead take a look at its dictionary meaning, especially in the context of computer science. Keep that simple fundamental in mind.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/Screen-Shot-2020-03-14-at-10.25.44-am.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Polling is simply having your client check on a server by sending it a network request and asking for updated data. These requests are typically made at regular intervals like 5 seconds, 15 seconds, 1 minute or any other interval required by your use case.</p>
<p>Polling every few seconds is still not quite the same as real-time, and also comes with the following downsides, especially if you have a million plus simultaneous users:</p>
<ul>
<li><p>almost-constant network requests (not great for the client)</p>
</li>
<li><p>almost constant inbound requests (not great for the server loads - 1 million+ requests per second!)</p>
</li>
</ul>
<p>So polling rapidly is not really efficient or performant, and polling is best used in circumstances when small gaps in data updates is not a problem for your application.</p>
<p>For example, if you built an Uber clone, you may have the driver-side app send driver location data every 5 seconds, and your rider-side app poll for the driver's location every 5 seconds.</p>
<h3 id="heading-streaming">Streaming</h3>
<p>Streaming solves the constant polling problem. If constantly hitting the server is necessary, then it's better to use something called <a target="_blank" href="https://en.wikipedia.org/wiki/WebSocket">web-sockets</a>.</p>
<p>This is a network communication protocol that is designed to work over TCP. It opens a two-way dedicated channel (socket) between a client and server, kind of like an open hotline between two endpoints.</p>
<p>Unlike the usual TCP/IP communication, these sockets are "long-lived" so that its a single request to the server that opens up this hotline for the two-way transfer of data, rather than multiple separate requests. By long-lived, we meant that the socket connection between the machines will last until either side closes it, or the network drops.</p>
<p>You may remember from our discussion on IP, TCP and HTTP that these operate by sending "packets" of data, for each request-response cycle. Web-sockets mean that there is a single request-response interaction (not a cycle really if you think about it!) and that opens up the channel through which two-data is sent in a "stream".</p>
<p>The big difference with polling and all "regular" IP based communication is that whereas polling has the client making requests to the server for data at regular intervals ("pulling" data), in streaming, the client is "on standby" waiting for the server to "push" some data its way. The server will send out data when it changes, and the client is always listening for that. Hence, if the data change is constant, then it becomes a "stream", which may be better for what the user needs.</p>
<p>For example, while using <a target="_blank" href="https://www.freecodecamp.org/news/p/51a1d601-c57e-48cf-8f8d-9bb1c333d64d/repl.it">collaborative coding IDEs</a>, when either user types something, it can show up on the other, and this is done via web-sockets because you want to have real-time collaboration. It would suck if what I typed showed up on your screen after you tried to type the same thing or after 3 minutes of you waiting wondering what I was doing!</p>
<p>Or think of online, multiplayer games - that is a perfect use case for streaming game data between players!</p>
<p>To conclude, the use case determines the choice between polling and streaming. In general, you want to stream if your data is "real-time", and if it's OK to have a lag (as little as 15 seconds is still a lag) then polling may be a good option. But it all depends on how many simultaneous users you have and whether they expect the data to be instantaneous. A commonly used example of a streaming service is <a target="_blank" href="https://en.wikipedia.org/wiki/Apache_Kafka">Apache Kafka</a>.</p>
<h2 id="heading-section-11-endpoint-protection">Section 11: Endpoint Protection</h2>
<p>When you build large scale systems it becomes important to protect your system from too many operations, where such operations are not actually needed to use the system. Now that sounds very abstract. But think of this - how many times have you clicked furiously on a button thinking it's going to make the system more responsive? Imagine if each one of those button clicks pinged a server and the server tried to process them all! If the throughput of the system is low for some reason (say a server was struggling under unusual load) then each of those clicks would have made the system even slower because it has to process them all!</p>
<p>Sometimes it's not even about protecting the system. Sometimes you want to limit the operations because that is part of your service. For example, you may have used free tiers on third-party API services where you're only allowed to make 20 requests per 30 minute interval. if you make 21 or 300 requests in a 30 minute interval, after the first 20, that server will stop processing your requests.</p>
<p>That is called rate-limiting. Using rate-limiting, a server can limit the number of operations attempted by a client in a given window of time. A rate-limit can be calculated on users, requests, times, payloads, or other things. Typically, once the limit is exceeded in a time window, for the rest of that window the server will return an error.</p>
<p>Ok, now you might think that endpoint "protection" is an exaggeration. You're just restricting the users ability to get something out of the endpoint. True, but it is also protection when the user (client) is malicious - like say a bot that is smashing your endpoint. Why would that happen? Because flooding a server with more requests than it can handle is a strategy used by malicious folks to bring down that server, which effectively brings down that service. That's exactly what a <a target="_blank" href="https://en.wikipedia.org/wiki/Denial-of-service_attack">Denial of Service (D0S) attack</a> is.</p>
<p>While DoS attacks can be defended against in this way, rate-limiting by itself won't protect you from a sophisticated version of a DoS attack - a <em>distributed</em> DoS. Here distribution simply means that the attack is coming from multiple clients that seem unrelated and there is no real way to identify them as being controlled by the single malicious agent. Other methods need to be used to protect against such coordinated, distributed attacks.</p>
<p>But rate-limiting is useful and popular anyway, for less scary use-cases, like the API restriction one I mentioned. Given how rate-limiting works, since the server has to first check the limit conditions and enforce them if necessary, you need to think about what kind of data structure and database you'd want to use to make those checks super fast, so that you don't slow down processing the request if it's within allowed limits. Also, if you have it in-memory within the server itself, then you need to be able to guarantee that all requests from a given client will come to that server so that it can enforce the limits properly. To handle situations like this it's popular to use a separate <a target="_blank" href="https://en.wikipedia.org/wiki/Redis">Redis service</a> that sits outside the server, but holds the user's details in-memory, and can quickly determine whether a user is within their permitted limits.</p>
<p>Rate limiting can be made as complicated as the rules you want to enforce, but the above section should cover the fundamentals and most common use-cases.</p>
<h2 id="heading-section-12-messaging-amp-pub-sub">Section 12: Messaging &amp; Pub-Sub</h2>
<p>When you design and build large-scale and <a target="_blank" href="https://blog.stackpath.com/distributed-system/">distributed systems</a>, for that system to work cohesively and smoothly, it is important to exchange information between the components and services that make up the system. But as we have seen before, systems that rely on networks suffer from the same weakness as networks - they are fragile. Networks fail and its not an infrequent occurrence. When networks fail, components in the system are not able to communicate and may degrade the system (best case) or cause the system to fail altogether (worst case). So distributed systems need robust mechanisms to ensure that the communication continues or recovers where it left off, even if there is an "arbitrary partition" (i.e. failure) between components in the system.</p>
<p>Imagine, as an example, that you're booking airline tickets. You get a good price, choose your seats, confirm the booking and you've even paid using your credit card. Now you're waiting for your ticket PDF to arrive in your inbox. You wait, and wait, and it never comes. Somewhere, there was a system failure that didn't get handled or recover properly. A booking system will often connect with airline and pricing APIs to handle the actual flight selection, fare summary, date and time of flight etc. All that gets done while you click through the site's booking UI. But it doesn't have to send you the PDF of the tickets until a few minutes later. Instead the UI can simply confirm that your booking is done, and you can expect the tickets in your inbox shortly. That's a reasonable and common user experience for bookings because the moment of paying and the receipt of the tickets does not have to be simultaneous - the two events can be asynchronous. Such a system would need messaging to ensure that the service (server endpoint) that asynchronously generates the PDF gets notified of a confirmed, paid-for booking, and all the details, and then the PDF can be auto-generated and emailed to you. But if that messaging system fails, the email service would never know about your booking and no ticket would get generated.</p>
<p><strong>Publisher / Subscriber Messaging</strong></p>
<p>This is a very popular paradigm (model) for messaging. The key concept is that publishers 'publish' a message and a subscriber subscribes to messages. To give greater granularity, messages can belong to a certain "topic" which is like a category. These topics are like dedicated "channels" or pipes, where each pipe exclusives handles messages belonging to a specific topic. Subscribers choose which topic they want to subscribe to and get notified of messages in that topic. The advantage of this system is that the publisher and the subscriber can be completely de-coupled - i.e. they don't need to know about each other. The publisher announces, and the subscriber listens for announcements for topics that it is on the lookout for.</p>
<p>A server is often the publisher of messages and there are usually several topics (channels) that get published to. The consumer of a specific topic subscribes to those topics. There is no direct communication between the server (publisher) and the subscriber (could be another server). The only interaction is between publisher and topic, and topic and subscriber.</p>
<p>The messages in the topic are just data that needs to be communicated, and can take on whatever forms you need. So that gives you four players in Pub/Sub: Publisher, Subscriber, Topics and Messages.</p>
<h3 id="heading-better-than-a-database">Better than a database</h3>
<p>So why bother with this? Why not just persist all data to a database and consume it directly from there? Well, you need a system to queue up the messages because each message corresponds to a task that needs to be done based on that message's data. So in our ticketing example, if 100 people make a booking in 35 minutes, putting all that in the database doesn't solve the problem of emailing those 100 people. It just stores a 100 transactions. Pub/Sub systems handle the communication, the task sequencing <em>and</em> the messages get persisted in a database. So the system can offer useful features like "at least once" delivery (messages won't be lost), persistent storage, ordering of messages, "try-again", "re-playability" of messages etc. Without this system, just storing the messages in the database will not help you ensure that the message gets delivered (consumed) and acted upon to successfully complete the task.</p>
<p>Sometimes the same message may get consumed more than once by a subscriber - typically because the network dropped out momentarily, and though the subscriber consumed the message, it didn't let the publisher know. So the publisher will simply re-send it to the subscriber. That's why the guarantee is "at least once" and not "once and only once". This is unavoidable in distributed systems because networks are inherently unreliable. This can raise complications, where the message triggers an operation on the subscriber's side, and that operation could change things in the database (change state in the overall application). What if a single operation gets repeated multiple times, and each time the application's state changes?</p>
<h3 id="heading-controlling-outcomes-one-or-many-outcomes">Controlling Outcomes - one or many outcomes?</h3>
<p>The solution to this new problem is called idempotency - which is a concept that is important but not intuitive to grasp the first few times you examine it. It is a concept that can appear complex (especially if you read the wikipedia entry), so for the current purpose, here is a user-friendly simplification <a target="_blank" href="https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation">from StackOverflow</a>:</p>
<blockquote>
<p><em>In computing, an idempotent operation is one that has no additional effect if it is called more than once with the same input parameters.</em></p>
</blockquote>
<p>So when a subscriber processes a message two or three times, the overall state of the application is exactly what it was after the message was processed the <em>first</em> time. If, for example, at the end of booking your flight tickets and after you entered your credit card details, you clicked on "Pay Now" three times because the system was slow ... you would not want to pay 3X the ticket price right? You need idempotency to ensure that each click after the <em>first</em> one doesn't make another purchase and charge your credit card more than once. In contrast, you can post an identical comment on your best friend's newsfeed N number of times. They will all show up as separate comments, and apart from being annoying, that's not actually <em>wrong.</em> Another example is offering "claps" on Medium posts - each clap is meant to increment the number of claps, not be one and only one clap. These latter two examples do not require idempotency, but the payment example does.</p>
<p>There are many flavours of messaging systems, and the choice of system is driven by the use-case to be solved for. Often, people will refer to "event based" architecture which means that the system relies on messages about "events" (like paying for tickets) to process operations (like emailing the ticket). The really commonly talked about services are Apache Kafka, RabbitMQ, Google Cloud Pub/Sub, AWS SNS/SQS.</p>
<h2 id="heading-section-13-smaller-essentials">Section 13: Smaller Essentials</h2>
<h3 id="heading-logging">Logging</h3>
<p>Over time your system will collect a lot of data. Most of this data is extremely useful. It can give you a view of the health of your system, its performance and problems. It can also give you valuable insight into who uses your system, how they use it, how often, which parts get used more or less, and so on.</p>
<p>This data is valuable for analytics, performance optimization and product improvement. It is also extremely valuable for debugging, not just when you log to your console during development, but in actually hunting down bugs in your test and production environments. So logs help in traceability and audits too.</p>
<p>The key trick to remember when logging is to view it as a sequence of consecutive events, which means the data becomes time-series data, and the tools and databases you use should be specifically designed to help work with that kind of data.</p>
<h3 id="heading-monitoring">Monitoring</h3>
<p>This is the next steps after logging. It answers the question of "What do I do with all that logging data?". You monitor and analyze it. You build or use tools and services that parse through that data and present you with dashboards or charts or other ways of making sense of that data in a human-readable way.</p>
<p>By storing the data in a specialized database designed to handle this kind of data (time-series data) you can plug in other tools that are built with that data structure and intention in mind.</p>
<h3 id="heading-alerting">Alerting</h3>
<p>When you are actively monitoring you should also put a system in place to alert you of significant events. Just like having an alert for stock prices going over a certain ceiling or below a certain threshold, certain metrics that you're watching may warrant an alert being sent if they go too high or too low. Response times (latency) or errors and failures are good ones to set up alerting for if they go above an "acceptable" level.</p>
<p>The key to good logging and monitoring is to ensure your data is fairly consistent over time, as working with inconsistent data could result in missing fields that then break the analytical tools or reduce the benefits of the logging.</p>
<h2 id="heading-resources">Resources</h2>
<p>As promised, some useful resources are as follows:</p>
<ol>
<li><p>A fantastic <a target="_blank" href="https://github.com/donnemartin/system-design-primer">Github repo</a> full of concepts, diagrams and study prep</p>
</li>
<li><p>Tushar Roy's introduction to <a target="_blank" href="https://www.youtube.com/watch?v=UzLMhqg3_Wc">Systems Design</a></p>
</li>
<li><p>Gaurav Sen's <a target="_blank" href="https://www.youtube.com/watch?v=quLrc3PbuIw&amp;list=PLMCXHnjXnTnvo6alSjVkgxV-VH6EPyvoX">YouTube playlist</a></p>
</li>
<li><p><a target="_blank" href="https://www.sitepoint.com/sql-vs-nosql-differences/">SQL vs NoSQL</a></p>
</li>
</ol>
<p>I hope you enjoyed this long-form guide!</p>
<p>If you would like to learn more about my journey from lawyer to software engineer, check out <a target="_blank" href="http://podcast.freecodecamp.org/53-zubin-pratap-from-lawyer-to-developer">episode 53</a> of the <a target="_blank" href="http://podcast.freecodecamp.org/">freeCodeCamp podcast</a> and also <a target="_blank" href="https://lessonsfromaquitter.com/episode207/">Episode 207</a> of "Lessons from a Quitter". These provide the blueprint for my career change.</p>
<p>If you are interested in teaching yourself to code, changing careers and becoming a professional coder, or <a target="_blank" href="https://www.freecodecamp.org/news/non-technical-and-looking-for-a-technical-co-founder-2c212c01d6da/">becoming your own technical co-founder</a>, please reach out <a target="_blank" href="http://linktree.com/zubinpratap">here</a>. You can also check out my free webinar on <a target="_blank" href="http://futurecoderstraining.com/">Career Change to Code</a> if that is what you're dreaming of.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Best Book for Technical Coding Interview Prep ]]>
                </title>
                <description>
                    <![CDATA[ By Zhia Chong Is this the best book for technical interviews? Technical coding interviews are notoriously difficult — almost borderline quiz-like for those unprepared. It can sometimes be a daunting task to navigate all the technical coding preparat... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/is-this-the-best-book-for-coding-interview-preparation/</link>
                <guid isPermaLink="false">66d461ced1ffc3d3eb89de88</guid>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 13 Mar 2020 06:39:02 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9c27740569d1a4ca304f.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Zhia Chong</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/1_aEcUKEZzN7l6D6W9HnMeOw.png" alt="Image" width="600" height="400" loading="lazy">
<em>Is this the best book for technical interviews?</em></p>
<p>Technical coding interviews are notoriously difficult — almost borderline quiz-like for those unprepared. It can sometimes be a daunting task to navigate all the technical coding preparation resources available online, and one might ask: <em>is there a single book/resource that best prepares for technical coding interviews?</em></p>
<p><em>Best</em>, is relative of course in this case. If you’re looking for a book that will teach you how to solve any coding question, guides you on how to design something like Instagram that scales to a billion users, and makes your sandwich while you’re at it, then this book definitely isn’t it. </p>
<p>But for polishing your technical chops and making sure you’re well prepared to face the programming challenges in an interview, this book comes darn close to it. </p>
<p>In today’s book review, I go over in <em>detail</em> the <strong>good</strong> and the <strong>bad</strong> of one of the top-selling books on Amazon for technical coding interviews: <a target="_blank" href="https://amzn.to/2Q6m9xB">Elements of Programming Interviews</a> (a.k.a <em>EPI</em>, and it’ll be referred to as such in the rest of this article).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/1_HrabnKvr0v48ijl-_Z1n1Q.png" alt="Image" width="600" height="400" loading="lazy">
<em>Elements of Programming Interviews</em></p>
<h2 id="heading-what-is-this-book-about">What is this book about?</h2>
<p>EPI is a book that focuses on preparing for technical software engineering interview questions that are commonly asked at tech companies. If you’re looking for a position as a software engineer, this book will have something for you.</p>
<p>EPI was written by 3 folks who’ve worked across some of the best-known tech companies in the world, the likes of Facebook, Google, Uber, and Microsoft. The authors have very strong technical backgrounds, and this is evidenced by the technical focus in the contents of the book.</p>
<p>The book itself is highly technical in nature and deep dives into fundamental computer science. The types of technical coding questions vary widely from string manipulation to graph traversals. The book also offers concrete tips and tricks for solving specific types of coding problems, and includes a cheatsheet to help ace technical questions.</p>
<h2 id="heading-the-good">The Good</h2>
<p>In short: EPI is a highly technical book that is well-suited for anyone looking to prepare for technical coding questions that revolve around data structures and algorithms.</p>
<p>The things that I particularly enjoyed:</p>
<ul>
<li>has many questions (300+) with detailed answers, compared to another popular book (Cracking The Coding Interview) that only has 170+</li>
<li>comes in 3 different versions: Java, Python and C++. Suitable for people who want to use the language of their choice</li>
<li>has a great cheatsheet (Chapter 4) that summarizes all the techniques and data structures you’d need</li>
<li>covers in detail every single data structure you need, algorithms you should know, and techniques you should know in a simple, understandable format</li>
<li>covers relevant technical topics you might get asked in a coding interview, like what is TCP/IP, how the Internet works, and how to capture relationships between different entities in schema design</li>
</ul>
<p>Those are some of the top-level points I enjoyed about the book. What I <em>really</em> enjoy is that the answers are very, <em>very</em> well constructed. </p>
<p>The answers often take a brute force/simplistic approach to the problems. The authors then provide concrete examples of how you can improve on the brute force approach. With each iteration, the authors point out where the limitations are and how you can solve them with incremental optimizations.</p>
<p>For example, EPI explains how to detect a cycle in a linked list. The first approach: use a hash map to store every node you traverse, and then check against the hash map to see if you’ve seen it. This does the job, albeit it takes additional space (so-called O(N) space complexity and O(N) time complexity). </p>
<p>The book then points out that the additional space is not required, and suggests that detecting cycles in a linked list can be done without additional space by manipulating the pointers instead. </p>
<p>It takes that same approach in explaining almost all the questions, so everyone can understand how to get from a rough solution to an optimized one.</p>
<p>For someone who’s rusty and looking to start preparing for interviews, EPI does a great job — every chapter starts off with a summary of the data structure or algorithm that you will learn, why the data structure is special, what are the strengths/weaknesses of said data structure and what you need to take note of.</p>
<p>In short, EPI is the notebook I wished I had when I was preparing for technical interviews. This is the book I’d give a friend who’s looking to prepare for technical interviews — aside from my best-selling <a target="_blank" href="https://docs.google.com/document/d/1ppHix7p9knzaal-Edn3GHQMcx1MM_USY6zPcsbBpR3U/edit">interviewing course</a> (Acing The Tech Interview), which prepares any candidate for the entire interview experience from resume preparation, behavioral questions to how to solve coding problems creatively. Classes fill up fast, so book your slot <a target="_blank" href="https://zhiachong.com/courses/">here</a> today.</p>
<h2 id="heading-the-bad">The Bad</h2>
<p>EPI has its downsides as well. Being a highly technical book, this means the book has its focus set on coding questions.</p>
<p>This, inadvertently, means that the book falls short in terms of other aspects of the technical interview process which are, arguably, just as important — offer negotiation, how to write a persuasive resume, what to do when you get an offer, how to handle behavioral questions etc.</p>
<p>In addition, the book goes into deep detail with data structures and algorithms, but only provides a high-level overview, to the point of being confusing due to lack of context, of various other important concepts like SQL, NoSQL, how to design a proper schema for a simple application and more. </p>
<p>The book sort of covers SQL design by explaining how to structure tables to capture entity relationships, but it does not explain more about JOINs or how to query the tables properly. I think understanding the <em>what</em> (SQL tables) is just as important as the <em>how</em> (queries).</p>
<p>EPI also has a chapter on systems designs, but the chapter does not cover distributed designs. I would’ve liked it better if the book had described in more details what distributed systems are or where to find more information about these.</p>
<h2 id="heading-is-this-a-good-book-for-me">Is this a good book for me?</h2>
<p>If you have ~$40 to spare and a big appetite to learn, I’d say so.</p>
<p>The book sells for $36 on average (there are 3 versions). This book is highly rated on Amazon.com, with an average of 4.53 stars across all 3 versions. The stats are as follows:</p>
<p>On <a target="_blank" href="https://amzn.to/2Q6m9xB">Amazon.com</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/1_hcA7BERAhmwNL-Z9tll1dQ.png" alt="Image" width="600" height="400" loading="lazy">
<em>Versions of EPI on Amazon.com</em></p>
<p>3 versions (as of March 12):</p>
<ul>
<li>Python: 169 ratings 4.3 ave</li>
<li>Java: 203 ratings 4.6 ave</li>
<li>C++: 436 ratings 4.7 ave</li>
</ul>
<p>In aggregate, there were a total of 808 reviews.</p>
<p>Some of the reviews:</p>
<blockquote>
<p>“.. the best algorithm/data structure I ever took”</p>
<p>“the code is of high quality, using meaningful variable names”</p>
<p>“this is a must-have book”</p>
</blockquote>
<h3 id="heading-now-should-you-buy-it">Now, should you buy it?</h3>
<p>I think that <strong>EPI is one of the best resources to prepare for technical coding interviews, bar none.</strong> Regardless of your experience level, there’s something in there for you. I particularly enjoy reading the book for its clear and concise explanations, and I use this book as a reference in my programming course.</p>
<p>If you want all the data structures, algorithms you need to know in a single, easy-to-read book, then EPI is the book for you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/1_9foCcsPPFO9AiOlnTKpvOw.png" alt="Image" width="600" height="400" loading="lazy">
<em>Designing Data Intensive Applications</em></p>
<p>For distributed systems designs, I recommend looking elsewhere. A good start is <a target="_blank" href="https://amzn.to/2Q6m9xB">Designing Data Intensive Applications</a>.</p>
<p>I love it for the depth and insights, and I recommend it to many students who are taking my <a target="_blank" href="http://bit.ly/interviewcourses">courses</a> as well.</p>
<h3 id="heading-resources-i-recommend">Resources I Recommend</h3>
<p><a target="_blank" href="https://amzn.to/33fcvOp">Designing Data Intensive Applications</a> — great resource for learning about distributed systems and how large-scale systems work.</p>
<p><a target="_blank" href="https://docs.google.com/document/d/1ppHix7p9knzaal-Edn3GHQMcx1MM_USY6zPcsbBpR3U/edit">Acing The Technical Interview</a> — my best-selling personal coaching course on how to ace technical interviews. We cover resume review, technical coding interview, behavioral questions and more.</p>
<p><a target="_blank" href="https://docs.google.com/document/d/1PeK69h4H82rwKjhactiE_sAIorCcZgXgXTY7k-nXpnE/edit#heading=h.hs0b333nsxch">Acing The Distributed Systems Design Interview</a> — my personal coaching course on designing large scale distributed systems. Learn about how to design features like Instagram Stories, Groupon, movie streaming sites like Netflix at scale.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I landed offers from Microsoft, Amazon, and Twitter without an Ivy League degree ]]>
                </title>
                <description>
                    <![CDATA[ By Zhia Chong This is for those of you out there who are about to start your job search and who may be worried that you can’t land a top-tier tech job without a Stanford CS degree. Someone told you that you’re not good enough to get a job at ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-landed-offers-from-microsoft-amazon-and-twitter-without-an-ivy-league-degree/</link>
                <guid isPermaLink="false">66d461c857503cc72873deea</guid>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ career advice ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Career development  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ careers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Facebook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ internships ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Interviews ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microsoft ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Twitter ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 23 Feb 2020 08:14:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/02/1_QuyFfwka5D5j7Z2IR4mcCQ.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Zhia Chong</p>
<p>This is for those of you out there who are about to start your job search and who may be worried that you can’t land a top-tier tech job without a Stanford CS degree. Someone told you that you’re not good enough to get a job at Microsoft or Facebook. </p>
<p>But I’m here to tell you that you can get that job. Here’s how I landed my dream job at Twitter.</p>
<p>Read more about my courses <a target="_blank" href="https://docs.google.com/document/d/1PeK69h4H82rwKjhactiE_sAIorCcZgXgXTY7k-nXpnE/edit?usp=sharing">here</a> to learn how I prepared.</p>
<p>You can read about my experiences after a year at Twitter <a target="_blank" href="https://www.freecodecamp.org/news/what-ive-learned-in-1-year-at-twitter-65150f5d4af2/">here</a>.</p>
<h3 id="heading-what-this-article-covers">What this article covers:</h3>
<ul>
<li>My background</li>
<li>How I landed interviews with top tech companies in the world: Facebook Google, Amazon, LinkedIn, Microsoft, Twitter, Pinterest, Snapchat, and others.</li>
<li>How I landed multiple offers as a full-time software engineer</li>
<li>Lessons from my interview experience</li>
<li>Subscribe <a target="_blank" href="http://eepurl.com/dnt9Sf">here</a> for more article updates from me</li>
</ul>
<p>If you prefer to watch my story instead, I made a video here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/83Reyvrs-VQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-background">Background</h2>
<p>I did not graduate from an Ivy league school. I went to a community college in Idaho for two years, and then finished my CS degree at a small Catholic university.</p>
<p>I started learning computer science in my junior year of college, because it sounded fun to me at the time. The only thing resembling a computer I had growing up was a Chinese copycat of the Nintendo SNES. Even then, it would break every time I put a cartridge in it.</p>
<p>To support myself through college, I took multiple part-time jobs like cleaning floors and working stand-up concessions.</p>
<p>When I graduated, I didn’t have a job lined up. I applied to as many big tech companies as I could, and had the good fortune of landing a few phone interviews.</p>
<p>At this point, I didn’t have a single notion of what a technical screen would be like, much less how to prepare for it. I headed into these interviews thinking that the interviewer would ask me what a linked list or binary tree was.</p>
<p>I <strong>didn’t pass</strong> any of those interviews.</p>
<h2 id="heading-moving-forward">Moving forward</h2>
<p>I didn’t delve too much into whether I was good. I knew that I could learn things fast. I just needed an opportunity.</p>
<p>As the saying goes, cast your net far and wide. So that’s what I did.</p>
<p>What I did next is something I’m particularly proud of. I wrote a simple Python script that scraped job listings on Craigslist with titles containing keywords from a list, and collected the emails in a spreadsheet. For the actual war story, you can read the article <a target="_blank" href="https://www.freecodecamp.org/news/how-i-built-a-web-crawler-to-automate-my-job-search-f825fb5af718/">here</a>.</p>
<p>It wasn’t the smartest solution, but people who post on Craigslist are surprisingly accurate with their titles.</p>
<p>Craigslist, however, didn’t like people scraping their website. To work around this, I ran my script through a VPN, and had a timer that would pause the script every few minutes or so. It wasn’t perfect, but it worked well enough.</p>
<p>In the end I collected about 500 emails from around San Francisco, Portland, Spokane, and Seattle. I filtered the results by how specific and recent they were, and kept improving it by adding more and more features.</p>
<p>As it turned out, there were a few bots in the market already that crawled Craigslist and sent out automated emails. These were mostly offshore companies that were looking to pitch their company to the US market.</p>
<p>One of my workarounds was that I crafted emails that used keywords from their listings in the title of my emails. I then added more details using the body of the postings to make it seem more personable. I did a quick A/B test, and the replies I received had increased quite a bit from around 2–3% to 10%.</p>
<p>Out of the 500 or so emails, I received about 50 replies, and landed phone screens with a small percentage of those. I stopped at 500 because I was short on time and needed to finalize a job as soon as possible. I was optimizing for results rather than reach at that point.</p>
<p>As luck would have it, I finally landed a job at a startup in Seattle as a junior software engineer. The startup was located in Kirkland at the time, so I had to take a 45-min bus ride to make it in time for the interview.</p>
<p>I then stayed there for the next 3.5 years, where I learned a great deal of stuff like Amazon AWS, EC2, DynamoDB, SQS, and Docker. I grew a lot during this period. I learned how to write modular, maintainable code. I learned how to reason about software design. And I learned how to handle people problems.</p>
<p>I was working next to a group of smart people who held jobs at Microsoft, Amazon, and LinkedIn, and I tried to be the “sponge” in the group. I absorbed anything and everything they threw at me. I believe this made a huge impact in my career.</p>
<h2 id="heading-startup-days">Startup Days</h2>
<p>During my stint at the startup, I worked almost exclusively on backend development, with some dev-ops in between. I started out writing some functions to add/modify a feature that were mostly small in scope. But it was a great opportunity to understand the codebase and get some code reviews.</p>
<p>A year into it, I started owning parts of the codebase, and then I was tasked with turning a set of features into a service. That was the start of the SOA phase for the startup. We started turning various components of the site into services, and that’s how I started learning more about RESTful services, authentication, AWS services, pub-sub, distributed systems and so forth.</p>
<p>The interesting part here is that <em>I didn’t learn about any of these through books or formal education.</em> Rather, I needed to get that set of features done and there were the bottlenecks.</p>
<p>So I thought, let’s go solve it!</p>
<p>There were many times where I was stuck in analysis paralysis — a state where I over-analyzed scenarios and ended up not able to make progress.</p>
<p>Those trying times were the <strong>greatest</strong> learning opportunities. I started to learn feature scoping, negotiations, monitoring, alerting, and documentation. Each step of the process revealed more things I needed to learn. I grew the most during these 2–3 years, both as an individual and software engineer.</p>
<h2 id="heading-how-i-prepared-for-my-interviews">How I prepared for my interviews</h2>
<p>After suffering through my first job search, I told myself that I must be prepared in future interviews.</p>
<p>I started preparing for interviews by charting out an overview of what I was good at, bad at, and where I could improve. I broke it down into three categories: <strong>data structures, algorithms, and system design.</strong></p>
<p>Having worked in PHP for most of my professional career, and C++ in college, I wanted to try something a little simpler and less verbose for interviewing.</p>
<p>For this reason, I picked Python. It is a great language to learn, easy to pick up, supports many data structures out of the box, and can be written quickly on the whiteboard. I learned Python by going through YouTube tutorials like <a target="_blank" href="https://www.youtube.com/watch?v=Z1Yd7upQsXY">these</a>, and also reading their documentation. I prefer Python 2.x, but you can go for either 2.x or 3.</p>
<p>Also, another reason why I picked Python is that it’s highly readable and easy to write on a whiteboard. Here’s a trivial comparison between C++ and Python.</p>
<p>A C++ program to sort in descending order:</p>
<pre><code class="lang-c++"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;bits/stdc++.h&gt;</span></span>
<span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> <span class="hljs-built_in">std</span>; 
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{   
    <span class="hljs-keyword">int</span> arr[] = {<span class="hljs-number">1</span>,<span class="hljs-number">10</span>,<span class="hljs-number">0</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>};
    <span class="hljs-keyword">int</span> n = size(arr)/<span class="hljs-keyword">sizeof</span>(arr[<span class="hljs-number">0</span>]);   
    sort(arr, arr + n, greater&lt;<span class="hljs-keyword">int</span>&gt;());   
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n; i++) {       
        <span class="hljs-built_in">cout</span> &lt;&lt; arr[i] &lt;&lt; <span class="hljs-string">" "</span>;   
    }    
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>Compare that with Python’s version:</p>
<pre><code class="lang-py">a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">1000</span>]
a.sort(reverse=<span class="hljs-literal">True</span>)
<span class="hljs-keyword">print</span> a
</code></pre>
<p>I’ve received feedback from interviewers to <strong>err on the side of brevity</strong> in an interview. In a 45-minute interview, you want to use most of your time solving the actual problem.</p>
<p>Pro tip: pick a language that’s less verbose so that you can write the code more quickly on the whiteboard.</p>
<h2 id="heading-preparation-mode">Preparation mode</h2>
<p>I spent about a week going through simple challenges on LeetCode, HackerRank, and Project Euler to familiarize myself with their interfaces, and to get used to writing code in Python.</p>
<p>The first week gave me insights into my competence level at certain programming languages. I spent another week going through some design challenges like “design X” and went as wide and deep as I could.</p>
<p>This was a lot of fun for me, because I often looked at iOS apps and tried to figure out how they did it. For example, how would you build Instagram from scratch? (I was asked this at Facebook.)</p>
<p>My background is in API designs and service-oriented architecture, so I took this opportunity to show how I would design my own version of Instagram. And because I have some iOS programming experience from my side-projects, I could talk a little bit about callbacks and push/long-polls here.</p>
<p>I started the conversation with some features I’d like to have on my own version of Instagram: likes, upload a photo, and a simple timeline. Feature scoping enabled me to build a very solid API because I know these scenarios well.</p>
<p>I then drew some pictures of a high-level design, of how the client would interact with the backend, and of how the backend would store the data.</p>
<p>I started small, and then added more components where needed and proactively sought where the bottlenecks were. I made educated guesses (read <strong>educated, not blind guesses</strong>) on what the requirements would be, and how each technology would fit in well. And also equally important, what technologies would <em>not fit well.</em></p>
<p>For example, why would you use Cassandra over MySQL to store certain information (hint: scale, speed of development, schema reviews), why use OAuth over simple authentication, Redis vs Memcached for caching data, streaming vs batch processing, and so on.</p>
<p>There are many areas you can explore here, so typically a one-hour session is not enough. To do well on these questions, you have to read and learn about trade-offs. Pros and cons of technologies in the industry. For this, I recommend a site like <a target="_blank" href="http://highscalability.com/all-time-favorites/">HighScalability</a>.</p>
<p>Take it like a typical brainstorming session with a coworker, so explore <em>as widely and as deeply</em> as you can.</p>
<p>It’s crucial to know that these design interviews are meant to explore how much you know and how well you know it, and it’s <strong>an opportunity for you to shine.</strong> I watched this YouTube <a target="_blank" href="https://www.youtube.com/watch?v=ZgdS0EUmn70">video</a> from an ex-Facebook engineer about how to solve design problems, and it gave me insights that helped me tremendously with my design interviews. My two main lessons from it: <strong>drive the design conversation,</strong> and <strong>show what you know</strong>.</p>
<p>I listed out my competency level for: <strong>data structures</strong> (linked list, hash map, binary tree, binary search tree, heap, array), <strong>algorithms</strong> (binary search, hashing, dynamic programming, sorting), and <strong>language-specific syntax and libraries</strong> (like sort, lambda for Python, appending, indexing).</p>
<p>I picked the area I was worst at, and started working on it: <strong>algorithms</strong>.</p>
<p>Algorithms have never been my forte. It’s been a while since my college days, and I didn’t spend much time doing binary search in my day-to-day career. I had an inkling of how each algorithm would perform, and in what scenarios to use them. But I wasn’t 100% comfortable with writing a binary search in under 10 mins. On a whiteboard. In front of an interviewer.</p>
<p>I also picked up a bunch of fine-point markers from <a target="_blank" href="https://www.amazon.com/86601-Low-Odor-Markers-Assorted-8-Count/dp/B000Z88D2E/ref=sr_1_3?ie=UTF8&amp;qid=1518801079&amp;sr=8-3&amp;keywords=white+board+pens">Amazon</a>, which work amazingly well. Perhaps it’s just me, but the fine-point markers in interviewing rooms usually don’t work at all. I’d usually scramble for 2–3 mins looking for a working pen, and that’s 2–3 mins you can’t afford to waste. Plus, fine-point markers allow you to write 5–8 more lines of code on a typical whiteboard vs. thicker ones. :)</p>
<p>Pro tip: Get your own set of fine-point markers.</p>
<p>I got a whiteboard from Costco for $50, some books from Amazon (listed in the tools I recommend section below), and started practicing. I made sure I ramped up on binary search, recursion, dynamic programming, BFS and DFS. A lot of interviewing questions revolved around recursion and binary search or some variations of it.</p>
<p>The best interviewing questions I’ve seen had many different solutions to them, and there’s an additional layer added on top as you progress through.</p>
<p>One Google question I had was related to file-system directories, and how to traverse them (hint: recursion). I solved that relatively quickly, and the interviewer asked how to identify a missing file in that directory. That was a little more difficult, but I got through it. And we then moved into how to rebuild the directory, how to serialize/deserialize it, and we spent a good chunk of time debating how file directories work underneath the hood. It was a very enjoyable session for me.</p>
<h2 id="heading-interviewing-at-top-tier-companies">Interviewing at top-tier companies</h2>
<p>It was a nerve-wracking experience, to say the least, and a real roller-coaster.</p>
<p>I allocated my time in the following manner: 20% resume, 20% research and 60% interview preparation.</p>
<p>I spent 20% of my time fixing up my resume, which hadn’t been updated in at least three years. I took a hard look at the stuff I’ve done in the past, and picked projects I handled end-to-end, <strong>regardless of complexity.</strong></p>
<p>The reason for doing this is two-fold. Taking a project from start to completion demands discipline and leadership — two of the traits I’d like to be identified with.</p>
<p>Secondly, ownership of a project end-to-end means I can talk about each aspect of the project <strong>at length and in depth.</strong> This proved critical in helping me navigate my design round at Twitter, where they grilled me hard on not only the designs of my projects, but also the decisions behind them.</p>
<p>20% of my time was used for research. Research in this case meant doing due diligence on companies I was interested in and reaching out for referrals. Having referrals helps with return calls.</p>
<p>From my experience, I sent out 20 or so cold messages to startups and mid-stage companies, and only heard back from a handful. But, almost all the companies I was referred to by an existing employee sent me a message within a week. This is anecdotal, but there’s value to be had there.</p>
<p>I am not that sociable, and I didn’t know many people who’d be able to refer me to a company I was interested in. To solve that problem, I went on LinkedIn. They have a search functionality that I used to search for 1st and 2nd-level connections. 2nd-level connections are people who’re one hop away from your immediate circle. In other words, we have mutual friends who can <strong>vouch for my credibility</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/linkedin-search.png" alt="Image" width="600" height="400" loading="lazy">
<em>LinkedIn search</em></p>
<p>This is incredibly important, because cold-calling someone for a job is very, very hard, especially in today’s market. People tend to err on the side of caution when it comes to cold-callers. Using LinkedIn was super helpful for my research phase.</p>
<p>Looking back at all the companies I interviewed at, here are my thoughts on each of them:</p>
<ul>
<li><strong>Facebook/Google</strong> — very mechanical. The standard interviewing process, and I didn’t feel any personal connection to them.</li>
<li><strong>Pinterest</strong> — not the best interviewing experience, but a cool product and company.</li>
<li><strong>Microsoft</strong> — loved the team and especially the manager and her manager. Standard interviewing questions, but very personable. Close-second choice. Your mileage may vary, though — each team at Microsoft interviews differently.</li>
<li><strong>Amazon</strong> — standard interviewing process. About 50% of the people love it, the others don’t.</li>
<li><strong>Twitter</strong> — incredibly fun and personal. Loved the interviewing process, gave a lot of emphasis on the individual and what I’d done in the past.</li>
<li><strong>Snapchat</strong> — cool office in LA, great bunch of people who decided to jump on the startup bandwagon. Felt like things were shrouded under a cloud of secrecy.</li>
<li><strong>Lyft</strong> — near to where I live, nice office, standard interviewing process. No strong feelings about it.</li>
</ul>
<h2 id="heading-lets-talk-about-my-favorite">Let’s talk about my favorite</h2>
<p>In many ways, I’d say Twitter’s interviewing style was hard. But at the same time, it was more interesting and personable than other companies I’ve interviewed at.</p>
<p>Their interviewing process starts with an introductory phone call with an engineering manager. That’s followed up by one or two technical phone screens, depending on how you perform. If you do well, they’ll fly you out to the office you’re interviewing for, which was Seattle in my case. There are three 1-hour-and-15-minute rounds, each with two interviewers.</p>
<p>The first two technical phone screens are the standard, run-of-the-mill technical screens where you solve coding problems on a shared coding doc.</p>
<p>The onsite rounds, however, are much more conversational and feel much less intimidating. The interviewers will ask you in-depth questions about your past projects, and they’ll grill you on what you’ve done in the past. If you claim ownership of a project, you should expect some questions about it. You’re encouraged to use them for references and to bounce ideas off of.</p>
<p>I never felt any pressure to magically come up with a fully working solution, and it felt highly collaborative.</p>
<h2 id="heading-the-others">The others</h2>
<p>In comparison, interviewing at Facebook and Google felt much more mechanical. They have one or two technical phone screens, and five to six onsite coding rounds. Each round involves some coding on a whiteboard, and you’re expected to come up with a near-perfect solution in a reasonable amount of time.</p>
<p>Facebook has two coding rounds, one design round, and one behavioral round.</p>
<p>I went through an additional shadow round at the end of the day, which didn’t count towards my overall score.</p>
<p>Google had five coding rounds, none of which focused on designs, and not a single interviewer asked about my previous projects. I don’t necessarily think this is bad. But I think it felt very mechanical and didn’t give much opportunity for the engineer to show what they’re capable of. Some people do well in these scenarios, much like some students do well in exams.</p>
<p>I <strong>did not enjoy</strong> my interview with Pinterest. I think the product itself is interesting, and their engineering team seems to be working on very cool technical <a target="_blank" href="https://medium.com/@Pinterest_Engineering">problems</a>. But I definitely had a negative experience during my interview there.</p>
<p>Pinterest has three coding rounds and one design round. Of those four rounds, the design round was most disappointing to me. Here’s why:</p>
<p>The interviewer came in late, and he spent a few minutes glancing over my resume before proceeding to draw some APIs on the board. He gave a short description of what he expected the API to do, and asked how I would solve it. We clarified the features of the API, and I started describing my solution using the whiteboard. About 5 minutes into it, I turned around and <strong>saw him taking a nap!</strong></p>
<p>Not cool.</p>
<p>I gave the recruiter my feedback in a survey, and I didn’t hear back from them after that.</p>
<p>I won’t delve into specifics of the questions I was asked during all the interviews. Instead, I’ll share some of the insights and useful tips I learned from my preparation process.</p>
<h2 id="heading-what-i-learned">What I learned:</h2>
<ul>
<li>Be <strong>honest</strong> on your resume. Most companies <em>will</em> ask you questions about your resume, and they can tell if you made it up. It’s better to be able to know <strong>100% about one project than to know 10% about 10 different projects.</strong></li>
<li>One-page resumes are <strong>recommended</strong>. This is especially true for tech companies, and it seems that the wisdom within the tech sphere is that you should reserve two pages and longer for post-doctoral work, or if you’ve done a lot of projects that you know and care deeply about. A friend of mine runs a <a target="_blank" href="https://www.jobscan.co/">company called Jobscan</a> that scans resumes and makes <em>specific, actionable</em> improvements on them. They’re pretty awesome, so try them out :)</li>
<li><strong>Socialize and establish a network</strong>. There’s a lot of competition for software engineering jobs, and these top tech companies are filtering through thousands of resumes a day. Having a referral will help you get some eyes on your resume.</li>
<li><strong>Nail</strong> your pitch. Every company that’s interested in you wants to know why you’re interested in them. <strong>A bad answer</strong>: I just need a job right now to pay bills. <strong>A less-bad answer</strong>: I was browsing online and found you guys. Sounds like you’re working on interesting things. <strong>A good answer</strong>: I know you’re doing some interesting work in X to achieve Y. I’ve done some work in the past and here’s what I learned about A, B, C that might be related to X. I am passionate about Y because blah. (<em>Don’t</em> use this as a template. Instead, you should see the pattern here — do your research, use your background, and show the company why both of you would fit well together.)</li>
</ul>
<h2 id="heading-some-more-advice">Some more advice</h2>
<p>Technical interviews are incredibly difficult, and sometimes it’s a hit-or-miss. The best opportunities, however, are reserved for those <em>who are prepared.</em></p>
<ul>
<li><strong>Prepare early, prepare <em>well</em></strong>. Everyone knows that they should prepare for an interview, but most don’t know how to do it <em>well</em>. As with anything worth doing, it takes deliberate practice to do well at something. And deliberate practice means you need to have a system.</li>
<li><strong>Build a system</strong> to practice technical skills. I started by rating myself from 1–10 on how good I was, and worked on the ones I was worst at. I spent days on different types of questions until I fully mastered each concept. And I <strong>wrote notes daily on Evernote</strong>. I had a note that serves as a brain dump for all things programming. It is full of programming tips &amp; tricks, common errors and misconceptions, frameworks for solving specific types of questions, and much more.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/my-notebook.png" alt="Image" width="600" height="400" loading="lazy">
<em>My notebook</em></p>
<ul>
<li><strong>Keep a notebook</strong> of the things you’ve learned. I use both <a target="_blank" href="http://evernote.com">Evernote</a> and <a target="_blank" href="http://onenote.com">OneNote</a> to keep track of things. OneNote for technical stuff/code, because I like that I can easily format the note any way I like. I use Evernote for essays/thoughts. The image above shows a note I keep on architecture and system designs.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/02/evernote.png" alt="Image" width="600" height="400" loading="lazy">
<em>Evernote for thoughts/tips</em></p>
<ul>
<li><strong>Jot everything down</strong>, even if you don’t think you’ll use it. I tend to forget very easily, so anything that I learn I write it down, including shell commands. I read technical blogs from time-to-time, and if I find anything interesting I jot it down on Evernote right away. I’ll revise it every week or month and reorganize accordingly. This has helped me tremendously over my career.</li>
<li><strong>Get mock interviews</strong>. This was definitely very valuable and I highly advise it. I had mock interviews with friends and tried to practice as much as I could. If you can’t find friends to practice with, then I recommend Refdash, which is an Interview-As-A-Service. They have a group of interviewers who work at big tech companies like Google, Facebook, and Microsoft. These interviewers will assess you on your coding and design skills. The best part of it is they’ll give you a score at the end of it with specific actionable items on how to improve.</li>
<li>It’s <strong>OK to fail. I failed multiple interviews during this whole process.</strong> Sometimes you just have a bad day. It’s not the end of the world if you fail. Companies are biased towards saying no because it’s a lower risk for them. A false positive costs more than a false negative in the long run. The first few rejections definitely stung the most. I failed multiple phone screens when I first started interviewing, and my confidence level sunk. I had doubts in my mind about my abilities and started fearing that my skills weren’t relevant in today’s job market. However, I gave myself a tip: If you fail 10 times, then try 10 times more. <em>All you need is one success.</em> That reassurance gave me a lot of confidence to keep pushing through and when my first offer came through, the other offers came much more easily.</li>
</ul>
<p>It took me about <strong>2 months</strong> of deliberate practice and preparation for my interviews. I spent about <strong>20 hours/week, or 80 hours/month,</strong> learning and writing notes on top of a full time job.</p>
<p>To build up my resume, it took 3.5 years of focused, deliberate work. I intentionally picked things that were tough and icky so that I could learn more than anyone else. Even though I don’t have a brand name university or top-tier tech company on my resume, I made up for it with a clear, thorough understanding of the projects I worked on. And this was possible because I researched and wrote down notes of everything I learned, and have a system to review them.</p>
<p>Remember: the strong survives, the tough thrives.</p>
<p>TL;DR: Don’t give up, set yourself up for opportunities, practice a lot, and stay hopeful. Focus on the process, and take a disciplined, dedicated approach to the process.</p>
<h3 id="heading-tools-i-recommend">Tools I Recommend</h3>
<ul>
<li><a target="_blank" href="https://amzn.to/2I80wup">Designing Data-Intensive Applications</a>: Awesome book for learning about scaling distributed systems! Highly recommended.</li>
<li><a target="_blank" href="http://amzn.to/2Dcs6Qd">Elements of Programming Interviews</a>: Great for solving coding problems.</li>
<li><a target="_blank" href="http://amzn.to/2Hj91OH">Cracking The Coding Interview</a>: Great for covering foundational CS coding problems.</li>
<li><a target="_blank" href="https://www.dailycodingproblem.com/zhiachong">Daily Coding Problem.com</a>: This is a free-to-try website that offers free daily coding problems. You can sign up for interesting daily coding challenges, and you can pay for solutions if you want.</li>
<li><a target="_blank" href="https://db.tt/tdUSP79S">Dropbox</a>: I keep all my files, pictures, resume here. Easy access, installed once and available everywhere. Love it ❤️ (If you sign up thru this link, both of us will get free 500MB!</li>
<li><a target="_blank" href="https://coderunnerapp.com/">CodeRunner</a>: I love this Mac app! I used this multiple times to run ad-hoc Python scripts/functions and it just works amazingly well. ?</li>
<li><a target="_blank" href="https://amzn.to/2D8FUxS">Kafka the Guide</a>: I used this book as a reference guide, and enjoyed it for the high-level description.</li>
</ul>
<p>(I share more resources I personally have used and recommend on <a target="_blank" href="http://zhiachong.com/resources">zhiachong.com</a>, if you’re interested in learning more.)</p>
<p>Thanks for reading my story! You can find me on <a target="_blank" href="https://twitter.com/zhiachong">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/zhiachong/">LinkedIn</a>. I would love to connect and talk more about tech, startups, travel :D</p>
<p><strong>Credits:</strong></p>
<p><a target="_blank" href="https://twitter.com/hakczar">Brandon O’brien</a>, my mentor and good friend, for proof-reading and providing valuable feedback on how to improve this article.</p>
<p><a target="_blank" href="https://medium.com/@yksugi">YK Sugishita</a>, an up-and-coming Youtube star who left his job at Google to pursue his dreams, for proof-reading and giving critical feedback.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
