<?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[ Oluwatobi - 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[ Oluwatobi - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 06 May 2026 14:39:05 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/Tobilyn77/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Streamline Search in Web Applications with Elasticsearch  ]]>
                </title>
                <description>
                    <![CDATA[ They say data is the new gold. But navigating through a large dataset to meet the demands of consumers in record time still gives backend devs a headache. Conventional database queries often aren't to ]]>
                </description>
                <link>https://www.freecodecamp.org/news/streamline-search-functionality-in-web-apps-with-elasticsearch/</link>
                <guid isPermaLink="false">69e10d82b67a275a9d505023</guid>
                
                    <category>
                        <![CDATA[ elasticsearch ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ indexing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Search Engines ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Thu, 16 Apr 2026 16:25:38 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/e6563d07-a253-4fd9-b1f6-54dc98a48319.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>They say data is the new gold. But navigating through a large dataset to meet the demands of consumers in record time still gives backend devs a headache.</p>
<p>Conventional database queries often aren't totally reliable in getting accurate search results fast. But fortunately, Elasticsearch comes to the rescue.</p>
<p>In this article, I'll walk you through how to use Elasticsearch to enhance database searches and analytics while still maintaining efficiency.</p>
<p>Here are the prerequisites for this tutorial:</p>
<ul>
<li><p>A Node.js environment</p>
</li>
<li><p>Basic backend knowledge</p>
</li>
</ul>
<p>With that, let's get started. But first of all, what is Elasticsearch?</p>
<h3 id="heading-table-of-content">Table of Content</h3>
<ul>
<li><p><a href="#heading-what-is-elasticsearch">What is Elasticsearch?</a></p>
</li>
<li><p><a href="#heading-elasticsearch-key-terms">Elasticsearch Key Terms</a></p>
</li>
<li><p><a href="#heading-how-to-set-up-elasticsearch">How to Set Up Elasticsearch</a></p>
</li>
<li><p><a href="#heading-how-to-set-up-the-demo-project">How to Set Up the Demo Project</a></p>
</li>
<li><p><a href="#heading-how-to-set-up-elasticsearch-in-your-project">How to Set Up Elasticsearch in Your Project</a></p>
</li>
<li><p><a href="#heading-how-to-work-with-indexes-in-elasticsearch">How to Work with Indexes in Elasticsearch</a></p>
</li>
<li><p><a href="#heading-search-implementation">Search Implementation</a></p>
</li>
<li><p><a href="#heading-full-code">Full Code</a></p>
</li>
<li><p><a href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-elasticsearch">What is Elasticsearch?</h2>
<p>Elasticsearch is a search engine built by Apache that can index words and phrases, providing advanced text and vector search capabilities. It also has other useful features such as search analytics and an auto-complete feature.</p>
<p>Note that Elasticsearch isn't a database, even though it does provide indexing features (which popular databases also do).</p>
<p>Other popular alternatives to this tool used in production environments include <a href="https://www.algolia.com/">Algolia</a>, <a href="https://opensearch.org/">OpenSearch</a> and <a href="https://www.meilisearch.com/">MeiliSearch</a>.</p>
<h2 id="heading-elasticsearch-key-terms">Elasticsearch Key Terms</h2>
<p>in this section, we'll go over some important terminology used in Elasticsearch. To ease your understanding, I'll make references to common database terminologies.</p>
<ul>
<li><p><strong>Index</strong>: This serves as a storage location for the data you're going to explore. It's like the database for Elasticsearch. It also shares other properties that DBs possess like uniqueness.</p>
</li>
<li><p><strong>Document:</strong> This is the smallest unit of information stored within the index. It's structurally identical to the MongoDB-based document and is also similar to rows in SQL-based databases.</p>
</li>
<li><p><strong>Mapping:</strong> Mapping refers to sets of rules or instructions that define how documents and fields are stored in the Elasticsearch index.</p>
</li>
<li><p><strong>Score:</strong> This is generated by Elasticsearch to show the degree of relevance of the search query to the stored index.</p>
</li>
<li><p><strong>Analyzer:</strong> When data is sent to the Elasticsearch engine for indexing, it initially passes through an analyzer which processes the text before indexing. This is achieved via Filters and Tokenizers.</p>
</li>
<li><p><strong>Tokenizers:</strong> This tool converts the gross unstructured data sent to the Elasticsearch engine into structured data tokens for further processing and storage.</p>
</li>
<li><p><strong>Aggregator:</strong> This search tool performs detailed analysis on the tokens stored in the index to generate actionable data insights. It's an advantage of the Elasticsearch engine. Mongo DB’s aggregator offer similar functions.</p>
</li>
<li><p><strong>Filter</strong>: A set of instructions which modifies tokens generated during the process of analysis. This could entail removal of fillers, capitalization rules, and so on.</p>
</li>
<li><p><strong>Bulk index:</strong> This refers to indexing more than one document at once. You typically do this when indexing a database with pre-existing content.</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-elasticsearch">How to Set Up Elasticsearch</h2>
<p>For the purpose of this tutorial, we'll use Elasticsearch's installable software on our local machine. Online hosted versions of Elasticsearch also exist which work hitch-free as well.</p>
<p><a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-with-zip-on-windows">Here</a> is a link detailing how to setup Elasticsearch on Windows. For non-Windows users, you can also install Elasticsearch on <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-from-archive-on-linux-macos">Linux/Mac OS</a> or use <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-with-docker">Docker</a>.</p>
<p><strong>Note</strong> that for Windows users, make sure you run Elasticsearch as an Administrator to avoid installation errors.</p>
<p>After successful installation, you can test if it's functioning by navigating to <code>localhost:9200</code> which serves as the default local endpoint for Elasticsearch. There you'll see a success message on the screen similar to the image below:</p>
<img src="https://cdn.hashnode.com/uploads/covers/64bba6ecb09308034572f437/ad94560d-7629-45f1-a94d-eaed0b61cefe.png" alt="elastic search localhost homepage" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>With that , we'll move on to setting up our project and integrating ElasticSearch into our demo project.</p>
<h2 id="heading-how-to-set-up-the-demo-project">How to Set Up the Demo Project</h2>
<p>For the sake of this tutorial, we will be utilizing a ready-built forum-based backend application built in Node Express JS. &nbsp;Here is the link to the project.</p>
<p>to get the project up and running, clone this package and run</p>
<p><code>npm start</code></p>
<p><code>MySQL</code> will serve as the default database for this tutorial. &nbsp;Let's now proceed to the next section.</p>
<h2 id="heading-how-to-set-up-elasticsearch-in-your-project">How to Set Up Elasticsearch in Your Project</h2>
<p>The existing demo project is a backend implementation of a forum site which allows users to post text content and facilitate discussions through category-based threads.</p>
<p>Elasticsearch is great for ensuring that users can sift through these posts and threads to accurately locate key content using distinct keywords. This is more effective than using traditional database search queries which can be cumbersome.</p>
<p>To set up Elasticsearch, start by installing the Elasticsearch <code>npm</code> package. To do this, run the command below in your project directory:</p>
<pre><code class="language-shell">npm install @elastic/elasticsearch
</code></pre>
<p>After successful installation, create a <code>config.js</code> file where you'll setup your driver to connect to your Elasticsearch application.</p>
<pre><code class="language-javascript">const { Client } = require('@elastic/elasticsearch');

const esClient = new Client({
  node: 'http://localhost:9200',
  auth: {
    username: process.env.ELASTICSEARCH_USERNAME,
    password: process.env.ELASTICSEARCH_PASSWORD
  },
  maxRetries: 5,
  requestTimeout: 60000,
  tls: {
    rejectUnauthorized: process.env.NODE_ENV !== 'development'
  }
});

module.exports = esClient;
</code></pre>
<p>To access and use Elasticsearch's capabilities within your backend application, you'll need to setup and configure your Elasticsearch driver. The details are specified in the config file code above.</p>
<p>As mentioned earlier, Elasticsearch runs on the <code>localhost:9200</code> port. So your Elasticsearch node will be directed to the localhost port. Online hosted Elasticsearch nodes will also work in similar scenarios.</p>
<p>Next in the config file, you'll provide the authentication credentials required to access Elasticsearch. The requested username and password will be supplied within the Auth object. If you're running Elasticsearch locally, authentication may not be required unless security is enabled.</p>
<p>In this scenario, <code>MaxRetries</code> refers to the number of maximum unsuccessful attempts to access Elasticsearch. In this case, we've pegged it at 5 attempts. <code>requestTimeout</code> is the time in milliseconds after which the request will automatically terminate if it's not processed.</p>
<p>Once you've completion the Config file, you'll import this config and initialize the Elasticsearch client when your backend starts.</p>
<h2 id="heading-how-to-work-with-indexes-in-elasticsearch">How to Work with Indexes in Elasticsearch</h2>
<p>Before we start harnessing the full power of Elasticsearch, we need to customize its search capabilities within the backend of the project. This involves setting up an index within the Elasticsearch Engine that indexes all posts made to the backend application.</p>
<pre><code class="language-javascript">const esClient = require('./config');

const setupIndex = async () =&gt; {
  try {
    const indexExists = await esClient.indices.exists({
      index: INDEX_NAME
    });

    if (indexExists) {
      console.log(`Index "${INDEX_NAME}" already exists`);
      return;
    }

    await esClient.indices.create({
      index: INDEX_NAME,
      ...indexMapping
    });

    console.log(`Index "${INDEX_NAME}" created`);
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<p>The code above highlights creating a new index. First, you need to invoke the <code>setupIndex()</code> function. Within this function, you're providing the preferred name for your index. &nbsp;Elasticsearch then checks if the name already exists within its indexes.</p>
<p>The function terminates if the index name already exists (to prevent duplication). But if it doesn't exist, it proceeds to create an index with that unique name alongside the index Mapping rules (which we'll discuss further shortly).</p>
<p>After creating the index, you'll see a success message in your application console.</p>
<h3 id="heading-how-to-delete-an-index">How to Delete an Index</h3>
<p>After a while, an index may no longer serve its purpose and you may need to remove it from Elasticsearch.</p>
<p>You can do this by executing the <code>esClient.indices.delete()</code> command as shown below:</p>
<pre><code class="language-javascript">const deleteIndex = async () =&gt; {
  try {
    await esClient.indices.delete({ index: INDEX_NAME });
    console.log(`${INDEX_NAME} deleted`);
  } catch (err) {
    console.error("Error deleting index:", err);
  }
};
</code></pre>
<h3 id="heading-how-to-delete-a-post-within-an-index">How to Delete a Post within an Index</h3>
<p>Sometimes, posts get deleted and modified. Also, users may get banned, after which you'd want to remove their content from the stored database .</p>
<p>In these cases, you'll want to ensure true deletion – that is, both from the database and from Elasticsearch indexed storage.</p>
<p>To do this, you'll call the <code>esClient.delete()</code> function, passing the Elasticsearch Client ID and the post's unique ID that you want to delete as callback arguments to your <code>esClient.delete</code> function.</p>
<pre><code class="language-javascript">const deletePost = async (postId) =&gt; {
  try {
    await esClient.delete({
      index: INDEX_NAME,
      id: postId.toString(),
    });

    console.log("Post successfully deleted");
    return { success: true, postId };
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<h3 id="heading-how-to-index-a-post">How to Index a Post</h3>
<p>After setting up the Elasticsearch Index, you'll want to automatically index posts made to the database into the Elasticsearch index.</p>
<p>To do this, you'll need to make sure that the post is compatible with your index schema via the <code>transformPostTOESRepo</code> function. This function extracts and formats the post data so it matches the Elasticsearch document structure.</p>
<pre><code class="language-javascript">const transformPostToESDoc = (post) =&gt; {
  return {
  id: post.id,
  title: post.title,
  content: post.body,
  author: post.author,
  category: post.category,
  tags: post.tags,
  views: post.views || 0,
  published_at: post.created_at
};

const indexPost = async (postId) =&gt; {
  try {
    const postRepo = await getPostRepo();
    const post = await postRepo.findOne({ where: { id: postId } });

    if (!post) {
      throw new Error("Post not available");
    }

    const esDocument = transformPostToESDoc(post);

    await esClient.index({
      index: INDEX_NAME,
      id: post.id.toString(),
      document: esDocument
    });

    console.log("Post successfully indexed");
    return { success: true, postId };
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<p>The post to be indexed must have a unique ID. For ease of use, we used the unique post ID constraint that comes by default in regular databases. Optionally, you can also use UUID libraries to generate unique post IDs.</p>
<p>The Post information is then attached to the <code>esClient.index()</code> function as the document to be indexed. We also put appropriate error handling measures in place to prevent the app from crashing if the process is unsuccessful.</p>
<h3 id="heading-how-to-define-elastic-search-mapping-rules">How to Define Elastic Search Mapping Rules</h3>
<p>Elasticsearch mappings define how your data is stored and indexed. They specify the data type of each field and how text is analyzed for search.</p>
<p>In the example below, we'll define an index configuration that includes custom analyzers for autocomplete and mappings for each post field (like title, content, and author).</p>
<pre><code class="language-javascript">const indexMapping = {
  settings: {
    analysis: {
      analyzer: {
        autocomplete: {
          type: 'custom',
          tokenizer: 'standard',
          filter: ['lowercase', 'autocomplete_filter']
        },
        autocomplete_search: {
          type: 'custom',
          tokenizer: 'standard',
          filter: ['lowercase']
        }
      },
      filter: {
        autocomplete_filter: {
          type: 'edge_ngram',
          min_gram: 2,
          max_gram: 10
        }
      }
    }
  },
  mappings: {
    properties: {
      id: { type: 'integer' },
      title: {
        type: 'text',
        analyzer: 'autocomplete',
        search_analyzer: 'autocomplete_search',
        fields: {
          keyword: { type: 'keyword' },
          standard: { type: 'text' }
        }
      },
      content: {
        type: 'text',
        analyzer: 'standard'
      },
      category: {
        type: 'keyword'
      },
      tags: { type: 'keyword' },
      author: {
        type: 'text',
        fields: {
          keyword: { type: 'keyword' }
        }
      },
      views: { type: 'integer' },
      published_at: { type: 'date' }
    }
  }
};
</code></pre>
<p>The <code>indexMapping</code> object defines how Elasticsearch should store and process your data. It consists of two main parts: <code>settings</code> and <code>mappings</code>.</p>
<p>The <code>mappings</code> section defines the structure of your documents. Each field (like <code>title</code>, <code>content</code>, or <code>author</code>) has a type such as <code>text</code>, <code>keyword</code>, <code>integer</code>, or <code>date</code>. This tells Elasticsearch how to store and search that field.</p>
<p>For text fields, we can also define analyzers. Analyzers control how text is broken into smaller pieces (tokens) during indexing and search.</p>
<p>In the <code>settings</code> section, we defined a custom analyzer for autocomplete. This uses an <code>edge_ngram</code> filter to generate partial word matches, so users can find results as they type. We also defined a separate <code>search_analyzer</code> to ensure that search queries are processed correctly.</p>
<p>Together, these settings allow you to support features like autocomplete while keeping search results accurate and efficient.</p>
<h2 id="heading-search-implementation">Search Implementation</h2>
<p>In order to implement your search functionality, you'll need to build out the API. This involves building the business logic service and the API route. You'll also use <code>GET</code> requests and attach your search term as a query. The result it generates will be received as a JSON document.</p>
<p>Then you'll implement the search post service function. In this scenario, you'll be using the search engine capabilities to search for phrases within the index. In line with best practices, you'll use a pagination technique to minimize&nbsp;receiving unwanted information.</p>
<p>The search query will consist of the index name, pagination parameters (<code>from</code> and <code>size</code>) to control which results are returned, and the expected maximum size of the result. &nbsp;You'll also attach a query object specifying the modality of the search that the Elasticsearch engine should use.</p>
<pre><code class="language-javascript">const searchElastic = async (query, page = 1, size = 10) =&gt; {
  const searchQuery = {
    index: INDEX_NAME,
    from: (page - 1) * size,
    size,
    query: {
      bool: {
        must: [
          {
            multi_match: {
              query,
              fields: ["title^3", "content"],
              type: "best_fields",
              fuzziness: "AUTO"
            }
          }
        ]
      }
    }
  };

  const result = await esClient.search(searchQuery);
  return result.hits.hits;
};
</code></pre>
<p>In the code above, the function is named <code>searchElastic</code>. The function contains three variables which must be passed in order to execute it: <code>size</code>, <code>page</code> and <code>query</code>.</p>
<p>The <code>size</code> variable specifies the maximum number of documents per search query to be returned. The default count could be any integer.</p>
<p>The query uses a <code>multi_match</code> clause to search across multiple fields, such as <code>title</code> and <code>content</code>. The <code>title^3</code> syntax boosts matches in the title, making them more relevant than matches in other fields.</p>
<p>We also included a <code>must</code> clause which defines conditions that documents must match to be included in the results.</p>
<p>The search results are usually ranked based on their degree of relevance to the search query.</p>
<h2 id="heading-full-code">Full Code</h2>
<p>With this, you've completed this tutorial and have configured Elasticsearch to index posts made to your database. Here's the full code:</p>
<ol>
<li>Elasticsearch Client (config.js):</li>
</ol>
<pre><code class="language-javascript">const { Client } = require('@elastic/elasticsearch');

const esClient = new Client({
  node: 'http://localhost:9200',
  auth: {
    username: process.env.ELASTICSEARCH_USERNAME,
    password: process.env.ELASTICSEARCH_PASSWORD
  },
  maxRetries: 5,
  requestTimeout: 60000,
  tls: {
    rejectUnauthorized: process.env.NODE_ENV !== 'development'
  }
});

module.exports = esClient;
</code></pre>
<ol>
<li>Index mapping:</li>
</ol>
<pre><code class="language-javascript">const indexMapping = {
  settings: {
    analysis: {
      analyzer: {
        autocomplete: {
          type: 'custom',
          tokenizer: 'standard',
          filter: ['lowercase', 'autocomplete_filter']
        },
        autocomplete_search: {
          type: 'custom',
          tokenizer: 'standard',
          filter: ['lowercase']
        }
      },
      filter: {
        autocomplete_filter: {
          type: 'edge_ngram',
          min_gram: 2,
          max_gram: 10
        }
      }
    }
  },
  mappings: {
    properties: {
      id: { type: 'integer' },
      title: {
        type: 'text',
        analyzer: 'autocomplete',
        search_analyzer: 'autocomplete_search',
        fields: {
          keyword: { type: 'keyword' },
          standard: { type: 'text' }
        }
      },
      content: {
        type: 'text',
        analyzer: 'standard'
      },
      category: {
        type: 'keyword'
      },
      tags: { type: 'keyword' },
      author: {
        type: 'text',
        fields: {
          keyword: { type: 'keyword' }
        }
      },
      views: { type: 'integer' },
      published_at: { type: 'date' }
    }
  }
};
</code></pre>
<ol>
<li>Create index:</li>
</ol>
<pre><code class="language-javascript">const setupIndex = async () =&gt; {
  try {
    const indexExists = await esClient.indices.exists({
      index: INDEX_NAME
    });

    if (indexExists) {
      console.log(`Index "${INDEX_NAME}" already exists`);
      return;
    }

    await esClient.indices.create({
      index: INDEX_NAME,
      ...indexMapping
    });

    console.log(`Index "${INDEX_NAME}" created`);
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<ol>
<li>Delete index:</li>
</ol>
<pre><code class="language-javascript">const deleteIndex = async () =&gt; {
  try {
    await esClient.indices.delete({ index: INDEX_NAME });
    console.log(`${INDEX_NAME} deleted`);
  } catch (err) {
    console.error("Error deleting index:", err);
  }
};
</code></pre>
<ol>
<li>Delete document (post):</li>
</ol>
<pre><code class="language-javascript">const deletePost = async (postId) =&gt; {
  try {
    await esClient.delete({
      index: INDEX_NAME,
      id: postId.toString()
    });

    console.log("Post successfully deleted");
    return { success: true, postId };
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<ol>
<li>Transform and index post:</li>
</ol>
<pre><code class="language-javascript">const transformPostToESDoc = (post) =&gt; {
  return {
  id: post.id,
  title: post.title,
  content: post.body,
  author: post.author,
  category: post.category,
  tags: post.tags,
  views: post.views || 0,
  published_at: post.created_at
};

const indexPost = async (postId) =&gt; {
  try {
    const postRepo = await getPostRepo();
    const post = await postRepo.findOne({ where: { id: postId } });

    if (!post) {
      throw new Error("Post not available");
    }

    const esDocument = transformPostToESDoc(post);

    await esClient.index({
      index: INDEX_NAME,
      id: post.id.toString(),
      document: esDocument
    });

    console.log("Post successfully indexed");
    return { success: true, postId };
  } catch (err) {
    console.error(err);
    throw err;
  }
};
</code></pre>
<ol>
<li>Search function:</li>
</ol>
<pre><code class="language-javascript">const searchElastic = async (query, page = 1, size = 10) =&gt; {
  const searchQuery = {
    index: INDEX_NAME,
    from: (page - 1) * size,
    size,
    query: {
      bool: {
        must: [
          {
            multi_match: {
              query,
              fields: ["title^3", "content"],
              type: "best_fields",
              fuzziness: "AUTO"
            }
          }
        ]
      }
    }
  };

  const result = await esClient.search(searchQuery);
  return result.hits.hits;
};
</code></pre>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Now you know how to use Elasticsearch to improve user search in your web applications. Elasticsearch is agnostic which allows you to use it across programming languages and frameworks. Its large community base also provides helpful user guides to make onboarding easier.</p>
<p>To further harness Elasticsearch's power, you can explore other tools within the <strong>ELK</strong> stack (Elasticsearch, Log Stash, and Kibana ) that'll help you generate high quality data visualizations for your data, especially for enterprise applications.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>A fast and reliable search engine isn’t negotiable in your web applications these days. Elasticsearch is your go-to for getting this done.</p>
<p>If you would like to read other articles that will enhance your tech journey, feel free to check out <a href="https://portfolio-oluwatobi.netlify.app/">my website here</a> . Stay active!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate Facial Recognition Authentication in a Social App with Face API ]]>
                </title>
                <description>
                    <![CDATA[ Social applications have evolved over the years, and there is a major need for secure methods to authenticate users' identities. Integrating multifactor authentication capabilities into applications is crucial for strengthening their integrity. In so... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/integrate-facial-recognition-authentication-in-a-social-application/</link>
                <guid isPermaLink="false">68d20d7a6bd072175081e6b2</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ facial recognition ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Tue, 23 Sep 2025 03:01:14 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758208687476/3ca6b95d-55c8-4bb6-a4aa-580409e1608f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Social applications have evolved over the years, and there is a major need for secure methods to authenticate users' identities.</p>
<p>Integrating multifactor authentication capabilities into applications is crucial for strengthening their integrity. In social apps, authentication mechanisms eliminate unwanted access to personal information between two parties. Facial authentication is not entirely new, as most devices have it built-in as security measure. It offers stronger protection compared to many traditional methods, especially against risks like phishing, brute-force attacks, and account hacking.</p>
<h2 id="heading-outline">Outline</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-to-expect">What to expect</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-brief-intro-to-the-face-api-tool">A Brief Intro to the Face API tool</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demo-project-integrating-facial-recognition-and-authentication">Demo Project: Integrating Facial Recognition and Authentication</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-information-and-tips">Additional Information and Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-to-expect">What to Expect</h2>
<p>In this article, I’ll walk you through creating a multi-factor authentication system for a chat application powered by <a target="_blank" href="https://getstream.io">Stream.io</a>, and ensuring efficient user face ID authentication to allow only authorized access to your app. I will illustrate all these with relevant code examples.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Here are the necessary prerequisites to follow along with this tutorial:</p>
<ul>
<li><p>Intermediate knowledge of Node.js/Express for the backend aspect</p>
</li>
<li><p>Knowledge of React for the frontend aspect</p>
</li>
<li><p><a target="_blank" href="https://getstream.io">Stream.io</a> API key</p>
</li>
</ul>
<p>Before we get started, we’ll briefly highlight the facial authentication tool of choice: <a target="_blank" href="https://justadudewhohacks.github.io/face-api.js/docs/index.html">Face-Api.js</a>.</p>
<h2 id="heading-a-brief-intro-to-the-face-api-tool">A Brief Intro to the Face API tool</h2>
<p>Face-Api.js is a facial recognition package designed for integration with JavaScript-powered applications. It was built on top of the Tensor flow library and provides extensive facial detection based on machine learning models and abstract calculations.</p>
<p>In addition to all these features, it's friendly to use and can also be used locally with its predefined models. Here is a link to its <a target="_blank" href="https://justadudewhohacks.github.io/face-api.js/docs/index.html">documentation page</a>, which provides relevant code examples.</p>
<p>It provides features such as face detection, face capture, and face match, which use the <a target="_blank" href="https://en.wikipedia.org/wiki/Euclidean_algorithm">Euclidean algorithm</a> to make precise distinctions. We'll now set it up alongside our chat application project in the next section.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>As mentioned earlier, this is a full-stack project containing both the frontend and the backend aspects. In this section, we’ll set up both code bases before proceeding to the demo project section.</p>
<h3 id="heading-frontend">Frontend</h3>
<p>We will power the application using the Vite framework for the frontend.</p>
<pre><code class="lang-javascript">npm create vite@latest
</code></pre>
<p>After creating the React application, install face-api.js with this command:</p>
<pre><code class="lang-javascript">npm i face-api.js
</code></pre>
<p>This will install the <code>face</code> package and the required dependencies. You can then install Stream’s powered chat SDK, which will form the main crux of the project.</p>
<pre><code class="lang-javascript">npm i stream-chat stream-chat-react
</code></pre>
<p>After successful completion, we are finally done with the project structure scaffold. To aid ease of local testing of our frontend application, we will have to host the face models needed by the Face package locally. Here is a <a target="_blank" href="https://github.com/justadudewhohacks/face-api.js-models">link</a> to the models. Kindly copy the model's folder and paste it into the public folder in the code project. Next, we’ll set up our backend project.</p>
<h3 id="heading-backend">Backend</h3>
<p>The backend is built to store user details and ensure user authentication before accessing the chat application. MongoDB will be the database of choice, and we will use the Express.js library as the backend API development environment of choice. For the ease of setup, kindly clone this <a target="_blank" href="https://github.com/oluwatobi2001/stream-backend.git">code-base</a> and install it on the local PC. It comes preloaded with the necessary installation files. To further enjoy a seamless backend experience, you can utilize the MongoDB <a target="_blank" href="https://www.mongodb.com/products/platform/atlas-database">Atlas</a> option as the database for storing user details. With that, we will now begin the code project in the next section.</p>
<h2 id="heading-demo-project-integrating-facial-recognition-and-authentication">Demo Project: Integrating Facial Recognition and Authentication</h2>
<p>In this section, we will walk through setting up an authentication page on the frontend where a user can register their details, username, email, and password on the registration page. They are also obliged to take a snapshot of their face, and the face API will be called to detect a face in the image. They won't be allowed to proceed beyond this until it is successful.</p>
<p>Thereafter, the image <code>faceDescriptor</code> function is called, which generates a unique face description vector value of the user’s face based on the machine learning models provided. These values are securely stored in the MongoDB database via the Express.js backend after successfully registering. The application is coupled to a multifactor authentication system, which has both the password based authentication and the facial authentication mechanisms.</p>
<p>When the first hurdle (password authentication) is completed, the user is then required to take a face match, comparing it with the user's face descriptor stored from the registration page. The comparison is achieved using the Euclidean algorithmic comparison based on the threshold we provide. If it meets the threshold, the face is said to be matched, and the user gets access to the chat application; else, the user is denied access to the Stream.io-powered chat application. Relevant source code snippets highlighting these steps will be provided concurrently with images.</p>
<p>We’ll begin by building a defunct registration page for our chat application using React, of course. We will begin by importing and initializing the necessary packages.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, {useState, useRef, useEffect} <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> faceapi <span class="hljs-keyword">from</span> <span class="hljs-string">'face-api.js'</span>
<span class="hljs-keyword">import</span> {useNavigate} <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> Register =<span class="hljs-function">()=&gt;</span> {

    <span class="hljs-keyword">const</span> navigate= useNavigate(<span class="hljs-string">"/"</span>)
    <span class="hljs-keyword">const</span> userRef = useRef();
    <span class="hljs-keyword">const</span> passwordRef= useRef();
    <span class="hljs-keyword">const</span> emailRef = useRef();
    <span class="hljs-keyword">const</span> FullRef = useRef()
</code></pre>
<p>In the code snippet above, we imported useful React hooks and initialized our installed <code>Face-api.js</code> tool. <a target="_blank" href="https://www.npmjs.com/package/axios">Axios</a> will serve as our API request tool of choice for this project. The <code>useRef</code> hook will be used to track the user inputs. We then defined the register function and initialized the various <code>useRef</code> hooks for the various input fields to be inputted.</p>
<pre><code class="lang-javascript">

    useEffect(<span class="hljs-function">()=&gt;</span> {
<span class="hljs-keyword">const</span> loadModels =<span class="hljs-keyword">async</span>() =&gt; {
<span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
<span class="hljs-keyword">await</span> faceapi.nets.faceLandmark68Net.loadFromUri(<span class="hljs-string">'/models'</span>);
<span class="hljs-keyword">await</span> faceapi.nets.faceRecognitionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
<span class="hljs-keyword">await</span> faceapi.nets.faceExpressionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
<span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
setModelIsLoaded(<span class="hljs-literal">true</span>);
                startVideo();
}
  loadModels()  }, [])
</code></pre>
<p>In the code above, the <code>useEffect</code> hook is called to ensure that the various locally stored <code>face-api</code> models are initialized and active in our application. The models are stored in the <code>models</code> sub-folder within the <code>public</code> folder. Going forward, after initializing our models, we will now set up our camcorder feature on our webpage.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [faceDetected, setFaceDetected] = useState(<span class="hljs-literal">false</span>);


        <span class="hljs-comment">// Start video feed</span>
        <span class="hljs-keyword">const</span> startVideo = <span class="hljs-function">() =&gt;</span> {
            navigator.mediaDevices
                .getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">true</span> })
                .then(<span class="hljs-function">(<span class="hljs-params">stream</span>) =&gt;</span> {
                    videoRef.current.srcObject = stream;
                })
                .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error accessing webcam: "</span>, err));
        };
        <span class="hljs-keyword">const</span> captureSnapshot = <span class="hljs-keyword">async</span> () =&gt; {
            <span class="hljs-keyword">const</span> canvas = snapshotRef.current;
            <span class="hljs-keyword">const</span> context = canvas.getContext(<span class="hljs-string">'2d'</span>);
            context.drawImage(videoRef.current, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
            <span class="hljs-keyword">const</span> dataUrl = canvas.toDataURL(<span class="hljs-string">'image/jpeg'</span>);
            setSnapshot(dataUrl);

            <span class="hljs-comment">// Generate the face descriptor (128-dimensional vector)</span>
            <span class="hljs-keyword">const</span> detection = <span class="hljs-keyword">await</span> faceapi
                .detectSingleFace(canvas, <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions())
                .withFaceLandmarks()
                .withFaceDescriptor();

            <span class="hljs-keyword">if</span> (detection) {
                <span class="hljs-keyword">const</span> newDescriptor = detection.descriptor;
                setDescriptionValue(newDescriptor)
                <span class="hljs-built_in">console</span>.log( newDescriptor);
               setSubmitDisabled(<span class="hljs-literal">false</span>)
                stopVid()
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"No face detected in snapshot"</span>);
            }
        };
    <span class="hljs-keyword">const</span> stopVid =<span class="hljs-function">() =&gt;</span> {

        navigator.mediaDevices
                .getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">false</span> })
                <span class="hljs-keyword">const</span> stream = videoRef?.current?.srcObject;
        <span class="hljs-keyword">if</span> (stream) {
            stream.getTracks().forEach(<span class="hljs-function"><span class="hljs-params">track</span> =&gt;</span> {track.stop()})
            videoRef.current.srcObject = <span class="hljs-literal">null</span>;
            setCameraActive(<span class="hljs-literal">false</span>)
        }
    }
        <span class="hljs-comment">// Detect face in the video stream</span>
        <span class="hljs-keyword">const</span> handleVideoPlay = <span class="hljs-keyword">async</span> () =&gt; {
            <span class="hljs-keyword">const</span> video = videoRef.current;
            <span class="hljs-keyword">const</span> canvas = canvasRef.current;

            <span class="hljs-keyword">const</span> displaySize = { <span class="hljs-attr">width</span>: video.width, <span class="hljs-attr">height</span>: video.height };
            faceapi.matchDimensions(canvas, displaySize);

            <span class="hljs-built_in">setInterval</span>(<span class="hljs-keyword">async</span> () =&gt; {
                <span class="hljs-keyword">if</span> (!cameraActive) <span class="hljs-keyword">return</span> ;
                <span class="hljs-keyword">const</span> detections = <span class="hljs-keyword">await</span> faceapi.detectAllFaces(
                    video,
                    <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions()
                );

                <span class="hljs-keyword">const</span> resizedDetections = faceapi.resizeResults(detections, displaySize);

                canvas.getContext(<span class="hljs-string">'2d'</span>).clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
                faceapi.draw.drawDetections(canvas, resizedDetections);
                    <span class="hljs-keyword">const</span> detected = detections.length &gt; <span class="hljs-number">0</span>;
                 <span class="hljs-keyword">if</span> (detected &amp;&amp; !faceDetected) {
                captureSnapshot();  <span class="hljs-comment">// Capture the snapshot as soon as a face is detected</span>
            }

                setFaceDetected(detections.length &gt; <span class="hljs-number">0</span>);
            }, <span class="hljs-number">100</span>);
        };
</code></pre>
<p>In the code above, we begin by defining a <code>useState</code> array when the user’s face is detected during the sign-up process. Thereafter, the function to trigger the browser camcorder is then activated. With this on, we can then trigger the <code>handlePlayFunction</code> in the code. This function monitors facial detection as highlighted by the face models already initialized. The <code>stopVid</code> function is also triggered when the user’s facial detection has been successfully completed.</p>
<p>In this section, we also activated the browser camcorder tool in our application to provide us with real time video. The <code>CaptureSnapshot</code> function helps to obtain a snapshot from the current video being showcased.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> RegSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
  e.preventDefault();
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hello"</span>);

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(BACKEND_URL, {
      <span class="hljs-attr">username</span>: userRef.current.value,
      <span class="hljs-attr">email</span>: emailRef.current.value,
      <span class="hljs-attr">FullName</span>: FullRef.current.value,
      <span class="hljs-attr">password</span>: passwordRef.current.value,
      <span class="hljs-attr">faceDescriptor</span>: descriptionValue,
    });

    <span class="hljs-built_in">console</span>.log(res.data);
    setError(<span class="hljs-literal">false</span>);
    navigate(<span class="hljs-string">"/login"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"help"</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(err);
    setError(<span class="hljs-literal">true</span>);
  }
};
</code></pre>
<p>With all the values obtained, the <code>regSubmit</code> function is then defined. When executed, it stores the provided user details with the face description object on our backend server which can then be accessed in the next section for authentication.</p>
<p>Below is the full registration code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> faceapi <span class="hljs-keyword">from</span> <span class="hljs-string">'face-api.js'</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-keyword">const</span> Register = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate(<span class="hljs-string">"/"</span>);

  <span class="hljs-keyword">const</span> userRef = useRef();
  <span class="hljs-keyword">const</span> passwordRef = useRef();
  <span class="hljs-keyword">const</span> emailRef = useRef();
  <span class="hljs-keyword">const</span> FullRef = useRef();
  <span class="hljs-keyword">const</span> snapshotRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> videoRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> canvasRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> [modelIsLoaded, setModelIsLoaded] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [detections, setDetections] = useState([]);
  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [snapshot, setSnapshot] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [cameraActive, setCameraActive] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [submitDisabled, setSubmitDisabled] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [descriptionValue, setDescriptionValue] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [faceDetected, setFaceDetected] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> loadModels = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceLandmark68Net.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceRecognitionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceExpressionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
      setModelIsLoaded(<span class="hljs-literal">true</span>);
      startVideo();
    };

    loadModels();
  }, []);

  <span class="hljs-keyword">const</span> RegSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hello"</span>);

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">'http://localhost:5000/v1/users'</span>, {
        <span class="hljs-attr">username</span>: userRef.current.value,
        <span class="hljs-attr">email</span>: emailRef.current.value,
        <span class="hljs-attr">FullName</span>: FullRef.current.value,
        <span class="hljs-attr">password</span>: passwordRef.current.value,
        <span class="hljs-attr">faceDescriptor</span>: descriptionValue
      });

      <span class="hljs-built_in">console</span>.log(res.data);
      setError(<span class="hljs-literal">false</span>);
      navigate(<span class="hljs-string">"/login"</span>);
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"help"</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">console</span>.log(err);
      setError(<span class="hljs-literal">true</span>);
    }
  };

  <span class="hljs-keyword">const</span> startVideo = <span class="hljs-function">() =&gt;</span> {
    navigator.mediaDevices
      .getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">true</span> })
      .then(<span class="hljs-function">(<span class="hljs-params">stream</span>) =&gt;</span> {
        videoRef.current.srcObject = stream;
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error accessing webcam: "</span>, err));
  };

  <span class="hljs-keyword">const</span> stopVid = <span class="hljs-function">() =&gt;</span> {
    navigator.mediaDevices.getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">false</span> });
    <span class="hljs-keyword">const</span> stream = videoRef?.current?.srcObject;
    <span class="hljs-keyword">if</span> (stream) {
      stream.getTracks().forEach(<span class="hljs-function">(<span class="hljs-params">track</span>) =&gt;</span> track.stop());
      videoRef.current.srcObject = <span class="hljs-literal">null</span>;
      setCameraActive(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">const</span> captureSnapshot = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> canvas = snapshotRef.current;
    <span class="hljs-keyword">const</span> context = canvas.getContext(<span class="hljs-string">'2d'</span>);
    context.drawImage(videoRef.current, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
    <span class="hljs-keyword">const</span> dataUrl = canvas.toDataURL(<span class="hljs-string">'image/jpeg'</span>);
    setSnapshot(dataUrl);

    <span class="hljs-keyword">const</span> detection = <span class="hljs-keyword">await</span> faceapi
      .detectSingleFace(canvas, <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions())
      .withFaceLandmarks()
      .withFaceDescriptor();

    <span class="hljs-keyword">if</span> (detection) {
      <span class="hljs-keyword">const</span> newDescriptor = detection.descriptor;
      setDescriptionValue(newDescriptor);
      <span class="hljs-built_in">console</span>.log(newDescriptor);
      setSubmitDisabled(<span class="hljs-literal">false</span>);
      stopVid();

      <span class="hljs-keyword">if</span> (storedDescriptor &amp;&amp; isMatchingFace(storedDescriptor, newDescriptor)) {
        <span class="hljs-built_in">setInterval</span>(alert(<span class="hljs-string">"face matched"</span>), <span class="hljs-number">100</span>);
      } <span class="hljs-keyword">else</span> {
        alert(<span class="hljs-string">"No Match Found!"</span>);
      }
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"No face detected in snapshot"</span>);
    }
  };

  <span class="hljs-keyword">const</span> handleVideoPlay = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> video = videoRef.current;
    <span class="hljs-keyword">const</span> canvas = canvasRef.current;
    <span class="hljs-keyword">const</span> displaySize = { <span class="hljs-attr">width</span>: video.width, <span class="hljs-attr">height</span>: video.height };
    faceapi.matchDimensions(canvas, displaySize);

    <span class="hljs-built_in">setInterval</span>(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">if</span> (!cameraActive) <span class="hljs-keyword">return</span>;

      <span class="hljs-keyword">const</span> detections = <span class="hljs-keyword">await</span> faceapi.detectAllFaces(
        video,
        <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions()
      );

      <span class="hljs-keyword">const</span> resizedDetections = faceapi.resizeResults(detections, displaySize);
      canvas.getContext(<span class="hljs-string">'2d'</span>).clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
      faceapi.draw.drawDetections(canvas, resizedDetections);

      <span class="hljs-keyword">const</span> detected = detections.length &gt; <span class="hljs-number">0</span>;
      <span class="hljs-keyword">if</span> (detected &amp;&amp; !faceDetected) {
        captureSnapshot();
      }

      setFaceDetected(detected);
    }, <span class="hljs-number">100</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col w-full h-screen justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mb-2 w-full"</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{RegSubmit}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mx-auto mb-5"</span>&gt;</span>Registration Page<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mb-2 w-[50%] mx-auto items-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full rounded-2xl h-[50px] border-2 p-2 mb-2 border-gray-900"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{emailRef}</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full rounded-2xl h-[50px] border-2 p-2 mb-2 border-gray-900"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{userRef}</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Full Name"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full rounded-2xl h-[50px] border-2 p-2 mb-2 border-gray-900"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{FullRef}</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full rounded-2xl h-[50px] border-2 p-2 mb-2 border-gray-900"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{passwordRef}</span>
            /&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              {!modelIsLoaded &amp;&amp; cameraActive &amp;&amp; !descriptionValue ? (
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              ) : (
                <span class="hljs-tag">&lt;&gt;</span>
                  {!descriptionValue &amp;&amp; (
                    <span class="hljs-tag">&lt;&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">video</span>
                        <span class="hljs-attr">ref</span>=<span class="hljs-string">{videoRef}</span>
                        <span class="hljs-attr">width</span>=<span class="hljs-string">"200"</span>
                        <span class="hljs-attr">height</span>=<span class="hljs-string">"160"</span>
                        <span class="hljs-attr">onPlay</span>=<span class="hljs-string">{handleVideoPlay}</span>
                        <span class="hljs-attr">autoPlay</span>
                        <span class="hljs-attr">muted</span>
                      /&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
                        <span class="hljs-attr">ref</span>=<span class="hljs-string">{canvasRef}</span>
                        <span class="hljs-attr">width</span>=<span class="hljs-string">"200"</span>
                        <span class="hljs-attr">height</span>=<span class="hljs-string">"160"</span>
                        <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">position:</span> '<span class="hljs-attr">absolute</span>', <span class="hljs-attr">top:</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">left:</span> <span class="hljs-attr">0</span> }}
                      /&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                        {faceDetected ? (
                          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> '<span class="hljs-attr">green</span>' }}&gt;</span>Face Detected<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                        ) : (
                          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">color:</span> '<span class="hljs-attr">red</span>' }}&gt;</span>No Face Detected<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                        )}
                      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
                        <span class="hljs-attr">ref</span>=<span class="hljs-string">{snapshotRef}</span>
                        <span class="hljs-attr">width</span>=<span class="hljs-string">"480"</span>
                        <span class="hljs-attr">height</span>=<span class="hljs-string">"360"</span>
                        <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">none</span>' }}
                      /&gt;</span>
                    <span class="hljs-tag">&lt;/&gt;</span>
                  )}
                <span class="hljs-tag">&lt;/&gt;</span>
              )}

              {snapshot &amp;&amp; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> '<span class="hljs-attr">20px</span>' }}&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">h4</span>&gt;</span>Face Snapshot:<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
                    <span class="hljs-attr">src</span>=<span class="hljs-string">{snapshot}</span>
                    <span class="hljs-attr">alt</span>=<span class="hljs-string">"Face Snapshot"</span>
                    <span class="hljs-attr">width</span>=<span class="hljs-string">"200"</span>
                    <span class="hljs-attr">height</span>=<span class="hljs-string">"160"</span>
                  /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{stopVid}</span>&gt;</span>
                Stop Video
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
              <span class="hljs-attr">disabled</span>=<span class="hljs-string">{submitDisabled}</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"mx-auto mt-4 rounded-2xl cursor-pointer text-white bg-primary w-[80%] lg:w-[50%] h-[40px] text-center items-center justify-center"</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
            &gt;</span>
              Register
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mt-1 w-full"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-center"</span>&gt;</span>
              Registered previously?<span class="hljs-symbol">&amp;nbsp;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-blue-600 underline"</span>&gt;</span>
                Login
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          {error &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-red-600 text-center mt-2"</span>&gt;</span>
              Error while registering, try again
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          )}
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Register;
</code></pre>
<p>Going forward, we will be working on our multifactor authentication system. In the code below, we will be highlighting the <code>loginSubmit</code> function which will be triggered when the user email and password credentials are provided for logging in to our chat application. The <code>useRef</code> hook is initialized which ensures that the values passed in the input boxes are parsed to the backend via the <code>Axios</code> request tool.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Link, useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Login</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> userRef = useRef();
  <span class="hljs-keyword">const</span> passwordRef = useRef();

  <span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> LoginSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">'http://localhost:5000/v1/auth/login'</span>,
        {
          <span class="hljs-attr">email</span>: userRef.current.value,
          <span class="hljs-attr">password</span>: passwordRef.current.value,
        },
        { <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span> }
      );

      <span class="hljs-built_in">console</span>.log(res?.data);
      setError(<span class="hljs-literal">false</span>);
      navigate(<span class="hljs-string">'/confirm-auth'</span>);
      <span class="hljs-built_in">console</span>.log(res);
    } <span class="hljs-keyword">catch</span> (err) {
      setError(<span class="hljs-literal">true</span>);
      <span class="hljs-built_in">console</span>.log(err);
    }
  };
}
</code></pre>
<p>The full login page code example will be provided <a target="_blank" href="http://github.com/oluwatobi2001/Stream-frontend.git">here</a>. After successfully confirming their identity via the use of the password authentication feature, we can then go on to confirm the user’s identity via the use of the face recognition system.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> React, { useRef, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> faceapi <span class="hljs-keyword">from</span> <span class="hljs-string">'face-api.js'</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
</code></pre>
<p>First of all, we will set up the app by importing the necessary dependencies as highlighted in the code snippet above.</p>
<pre><code class="lang-javascript">
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> loadModels = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceLandmark68Net.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceRecognitionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceExpressionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
    };

    loadModels();
  }, []);

  <span class="hljs-keyword">const</span> handleVideoPlay = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> video = videoRef.current;
    <span class="hljs-keyword">const</span> canvas = canvasRef.current;

    <span class="hljs-keyword">const</span> displaySize = { <span class="hljs-attr">width</span>: video.width, <span class="hljs-attr">height</span>: video.height };
    faceapi.matchDimensions(canvas, displaySize);

    <span class="hljs-built_in">setInterval</span>(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">if</span> (!cameraActive) <span class="hljs-keyword">return</span>;

      <span class="hljs-keyword">const</span> detections = <span class="hljs-keyword">await</span> faceapi.detectAllFaces(
        video,
        <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions()
      );

      <span class="hljs-keyword">const</span> resizedDetections = faceapi.resizeResults(detections, displaySize);
      canvas.getContext(<span class="hljs-string">'2d'</span>).clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
      faceapi.draw.drawDetections(canvas, resizedDetections);

      <span class="hljs-keyword">const</span> detected = detections.length &gt; <span class="hljs-number">0</span>;
      <span class="hljs-keyword">if</span> (detected &amp;&amp; !faceDetected) {
        captureSnapshot();
      }

      setFaceDetected(detected);
    }, <span class="hljs-number">100</span>);
  };

  <span class="hljs-keyword">const</span> startVideo = <span class="hljs-function">() =&gt;</span> {
    navigator.mediaDevices
      .getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">true</span> })
      .then(<span class="hljs-function">(<span class="hljs-params">stream</span>) =&gt;</span> {
        videoRef.current.srcObject = stream;
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error accessing webcam: "</span>, err));
  };

  <span class="hljs-keyword">const</span> stopVid = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> stream = videoRef.current.srcObject;
    <span class="hljs-keyword">if</span> (stream) {
      stream.getTracks().forEach(<span class="hljs-function">(<span class="hljs-params">track</span>) =&gt;</span> track.stop());
      videoRef.current.srcObject = <span class="hljs-literal">null</span>;
      setCameraActive(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">const</span> deleteImage = <span class="hljs-function">() =&gt;</span> {
    setSnapshot(<span class="hljs-literal">null</span>);
    setDescriptionValue(<span class="hljs-literal">null</span>);
    setFaceDetected(<span class="hljs-literal">false</span>);
    setCameraActive(<span class="hljs-literal">true</span>);
    startVideo();
  };

  <span class="hljs-keyword">const</span> captureSnapshot = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> canvas = snapshotRef.current;
    <span class="hljs-keyword">const</span> context = canvas.getContext(<span class="hljs-string">'2d'</span>);
    context.drawImage(videoRef.current, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

    <span class="hljs-keyword">const</span> dataUrl = canvas.toDataURL(<span class="hljs-string">'image/jpeg'</span>);
    setSnapshot(dataUrl);
    stopVid();

    <span class="hljs-keyword">const</span> detection = <span class="hljs-keyword">await</span> faceapi
      .detectSingleFace(canvas, <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions())
      .withFaceLandmarks()
      .withFaceDescriptor();

    <span class="hljs-keyword">if</span> (detection) {
      <span class="hljs-keyword">const</span> newDescriptor = detection.descriptor;
      setDescriptionValue(newDescriptor);
      <span class="hljs-built_in">console</span>.log(newDescriptor);
    }
  };
</code></pre>
<p>After initializing all the necessary dependencies, we also imported our models as we did in the registration page to detect the user’s face and then generate a face description. We also allowed for the user to delete the snapshot and retake the image as many times as possible.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> FaceAuthenticate = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">'http://localhost:5000/v1/auth/face-auth'</span>,
        { <span class="hljs-attr">faceDescriptor</span>: descriptionValue },
        { <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span> }
      );

      <span class="hljs-built_in">console</span>.log(res?.data);
      navigate(<span class="hljs-string">'/chat'</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">console</span>.log(err);
    }
  };
</code></pre>
<p>After the face descriptor object gets generated, we then sent it to the backend to compare it with the stored face descriptor obtained at the point of registration. If they match, we get redirected to the chat application. Otherwise, an appropriate error message denying us access to the chat application is displayed.</p>
<p>Here is the code to the <code>FaceAuth</code> page:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> React, { useRef, useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> faceapi <span class="hljs-keyword">from</span> <span class="hljs-string">'face-api.js'</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">const</span> FaceAuth = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate(<span class="hljs-string">"/"</span>);

  <span class="hljs-keyword">const</span> videoRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> canvasRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> snapshotRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> [cameraActive, setCameraActive] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [snapshot, setSnapshot] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [descriptionValue, setDescriptionValue] = useState(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [faceDetected, setFaceDetected] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> loadModels = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> faceapi.nets.tinyFaceDetector.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceLandmark68Net.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceRecognitionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
      <span class="hljs-keyword">await</span> faceapi.nets.faceExpressionNet.loadFromUri(<span class="hljs-string">'/models'</span>);
    };

    loadModels();
  }, []);

  <span class="hljs-keyword">const</span> handleVideoPlay = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> video = videoRef.current;
    <span class="hljs-keyword">const</span> canvas = canvasRef.current;

    <span class="hljs-keyword">const</span> displaySize = { <span class="hljs-attr">width</span>: video.width, <span class="hljs-attr">height</span>: video.height };
    faceapi.matchDimensions(canvas, displaySize);

    <span class="hljs-built_in">setInterval</span>(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">if</span> (!cameraActive) <span class="hljs-keyword">return</span>;

      <span class="hljs-keyword">const</span> detections = <span class="hljs-keyword">await</span> faceapi.detectAllFaces(
        video,
        <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions()
      );

      <span class="hljs-keyword">const</span> resizedDetections = faceapi.resizeResults(detections, displaySize);
      canvas.getContext(<span class="hljs-string">'2d'</span>).clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
      faceapi.draw.drawDetections(canvas, resizedDetections);

      <span class="hljs-keyword">const</span> detected = detections.length &gt; <span class="hljs-number">0</span>;
      <span class="hljs-keyword">if</span> (detected &amp;&amp; !faceDetected) {
        captureSnapshot();
      }

      setFaceDetected(detected);
    }, <span class="hljs-number">100</span>);
  };

  <span class="hljs-keyword">const</span> startVideo = <span class="hljs-function">() =&gt;</span> {
    navigator.mediaDevices
      .getUserMedia({ <span class="hljs-attr">video</span>: <span class="hljs-literal">true</span> })
      .then(<span class="hljs-function">(<span class="hljs-params">stream</span>) =&gt;</span> {
        videoRef.current.srcObject = stream;
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error accessing webcam: "</span>, err));
  };

  <span class="hljs-keyword">const</span> stopVid = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> stream = videoRef.current.srcObject;
    <span class="hljs-keyword">if</span> (stream) {
      stream.getTracks().forEach(<span class="hljs-function">(<span class="hljs-params">track</span>) =&gt;</span> track.stop());
      videoRef.current.srcObject = <span class="hljs-literal">null</span>;
      setCameraActive(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">const</span> deleteImage = <span class="hljs-function">() =&gt;</span> {
    setSnapshot(<span class="hljs-literal">null</span>);
    setDescriptionValue(<span class="hljs-literal">null</span>);
    setFaceDetected(<span class="hljs-literal">false</span>);
    setCameraActive(<span class="hljs-literal">true</span>);
    startVideo();
  };

  <span class="hljs-keyword">const</span> captureSnapshot = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> canvas = snapshotRef.current;
    <span class="hljs-keyword">const</span> context = canvas.getContext(<span class="hljs-string">'2d'</span>);
    context.drawImage(videoRef.current, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

    <span class="hljs-keyword">const</span> dataUrl = canvas.toDataURL(<span class="hljs-string">'image/jpeg'</span>);
    setSnapshot(dataUrl);
    stopVid();

    <span class="hljs-keyword">const</span> detection = <span class="hljs-keyword">await</span> faceapi
      .detectSingleFace(canvas, <span class="hljs-keyword">new</span> faceapi.TinyFaceDetectorOptions())
      .withFaceLandmarks()
      .withFaceDescriptor();

    <span class="hljs-keyword">if</span> (detection) {
      <span class="hljs-keyword">const</span> newDescriptor = detection.descriptor;
      setDescriptionValue(newDescriptor);
      <span class="hljs-built_in">console</span>.log(newDescriptor);
    }
  };

  <span class="hljs-keyword">const</span> FaceAuthenticate = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">'http://localhost:5000/v1/auth/face-auth'</span>,
        { <span class="hljs-attr">faceDescriptor</span>: descriptionValue },
        { <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span> }
      );

      <span class="hljs-built_in">console</span>.log(res?.data);
      navigate(<span class="hljs-string">'/chat'</span>);
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">console</span>.log(err);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex w-full h-screen flex-col justify-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mx-auto items-center text-lg font-semibold mb-3"</span>&gt;</span>
          Take a snapshot to confirm your identity
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-center mb-4"</span>&gt;</span>Ensure that the picture is taken in a bright area<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{startVideo}</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"flex w-[30%] mx-auto text-center items-center justify-center mb-5 h-[40px] bg-blue-600 rounded-md text-white"</span>
        &gt;</span>
          Turn on Webcam
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

        {!snapshot ? (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">video</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"flex mx-auto items-center rounded-md"</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{videoRef}</span>
              <span class="hljs-attr">width</span>=<span class="hljs-string">"240"</span>
              <span class="hljs-attr">height</span>=<span class="hljs-string">"180"</span>
              <span class="hljs-attr">onPlay</span>=<span class="hljs-string">{handleVideoPlay}</span>
              <span class="hljs-attr">autoPlay</span>
              <span class="hljs-attr">muted</span>
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span>
              <span class="hljs-attr">ref</span>=<span class="hljs-string">{snapshotRef}</span>
              <span class="hljs-attr">width</span>=<span class="hljs-string">"240"</span>
              <span class="hljs-attr">height</span>=<span class="hljs-string">"180"</span>
              <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">position:</span> '<span class="hljs-attr">absolute</span>', <span class="hljs-attr">top:</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">left:</span> <span class="hljs-attr">0</span> }}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{captureSnapshot}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-4 mx-auto block text-sm text-blue-600 underline"</span>&gt;</span>
              Take a snapshot
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span>
        ) : (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex w-full justify-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">{snapshot}</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"rounded-lg"</span>
              <span class="hljs-attr">width</span>=<span class="hljs-string">"240"</span>
              <span class="hljs-attr">height</span>=<span class="hljs-string">"180"</span>
              <span class="hljs-attr">alt</span>=<span class="hljs-string">"Face Snapshot"</span>
            /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        )}

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-row w-full justify-evenly mt-5"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{deleteImage}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-purple-500 text-white p-2 h-[35px] rounded-lg"</span>
          &gt;</span>
            Delete Image
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{FaceAuthenticate}</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-purple-500 text-white p-2 h-[35px] rounded-lg"</span>
          &gt;</span>
            Upload Image
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FaceAuth;
</code></pre>
<p>Displayed below is how the face authentication page should look like.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcPFsPVo9dymrTmMCyskCszbMf_SdG2n_j5gd7ayT1nQ6jOlhX8a_KFRG51cnqMCxUqFaVgTR2hrdGipmudd9B2TQpNfm4FrFMlYRo7bbu1gtRq1bKB5FmPi4QcbEPTLyDtAPbNEA?key=bLpVfispbJQQ4phtxWLC7w" alt="facial authentication page " width="600" height="400" loading="lazy"></p>
<p>Having set up the frontend, let's head to the backend and configure the registration and login endpoint for our project. The entire code to the backend project can be gotten <a target="_blank" href="http://github.com/oluwatobi2001/stream-backend.git">here</a>. We will only be highlighting the <code>faceAuth</code> backend function in this article.</p>
<p>To verify authentication, we will be using the sessions option instead of the JWT option. Important user information will be stored and accessed in the session cookies attached to the requests and responses to the frontend. Here is the <code>faceAuth</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> faceAuth = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(req.session);

    <span class="hljs-keyword">const</span> id = req.session.passport?.user;
    <span class="hljs-built_in">console</span>.log(id);


    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findById(id);
    <span class="hljs-built_in">console</span>.log(user);

    <span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">err</span>: <span class="hljs-string">"User not found"</span> });
    }


  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(err);
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">err</span>: <span class="hljs-string">"Internal Server Error"</span> });
  }
};
</code></pre>
<p>First, we defined an asynchronous function named <code>faceAuth</code>. We then obtained the unique ID of the user who had successfully scaled over the initial login process from the request session.</p>
<p>To confirm the similarity of the user's stored face descriptor and the picture sent from the frontend, we utilized the matching face function based on the Euclidean algorithm to confirm the user's identity as done below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> isMatchingFace = <span class="hljs-function">(<span class="hljs-params">descriptor1, descriptor2, threshold = <span class="hljs-number">0.6</span></span>) =&gt;</span> {
  <span class="hljs-comment">// Convert the stored descriptors to Float32Array if they aren't already</span>
  <span class="hljs-keyword">if</span> (!(descriptor1 <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Float32Array</span>)) {
    descriptor1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Float32Array</span>(<span class="hljs-built_in">Object</span>.values(descriptor1));
  }

  <span class="hljs-keyword">if</span> (!(descriptor2 <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Float32Array</span>)) {
    descriptor2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Float32Array</span>(<span class="hljs-built_in">Object</span>.values(descriptor2));
  }

  <span class="hljs-keyword">const</span> distance = faceapi.euclideanDistance(descriptor1, descriptor2);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Euclidean Distance:"</span>, distance);

  <span class="hljs-keyword">return</span> distance &lt; threshold;
};
</code></pre>
<p>As stated in the code above, the threshold of similarity of comparison used was 0.6. This is flexible and can be modified to suit the user's preference, as a higher threshold will provide better accuracy overall.<br>If the function returns true, then the user has been successfully authenticated and can then have access to our chat application. Here is the full code snippet.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> faceAuth = <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(req.session);

    <span class="hljs-keyword">const</span> id = req.session.passport?.user;
    <span class="hljs-built_in">console</span>.log(id);

    <span class="hljs-keyword">const</span> { faceDescriptor } = req.body;
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findById(id);
    <span class="hljs-built_in">console</span>.log(user);

    <span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>) {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">err</span>: <span class="hljs-string">"User not found"</span> });
    }

    <span class="hljs-keyword">const</span> isMatchingFace = <span class="hljs-function">(<span class="hljs-params">descriptor1, descriptor2, threshold = <span class="hljs-number">0.6</span></span>) =&gt;</span> {
      <span class="hljs-comment">// Convert the stored descriptor (object) to a Float32Array</span>
      <span class="hljs-keyword">if</span> (!(descriptor1 <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Float32Array</span>)) {
        descriptor1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Float32Array</span>(<span class="hljs-built_in">Object</span>.values(descriptor1));
      }

      <span class="hljs-keyword">if</span> (!(descriptor2 <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Float32Array</span>)) {
        descriptor2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Float32Array</span>(<span class="hljs-built_in">Object</span>.values(descriptor2));
      }

      <span class="hljs-keyword">const</span> distance = faceapi.euclideanDistance(descriptor1, descriptor2);
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Euclidean Distance:"</span>, distance);

      <span class="hljs-keyword">return</span> distance &lt; threshold;
    };

    <span class="hljs-keyword">if</span> (isMatchingFace(faceDescriptor, user.faceDescriptor)) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Face match successful"</span>);
      req.session.mfa = <span class="hljs-literal">true</span>;

      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
        <span class="hljs-attr">msg</span>: <span class="hljs-string">"User authentication was successful. Proceed to the chat app."</span>,
      });
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ <span class="hljs-attr">msg</span>: <span class="hljs-string">"Face does not match. Access denied."</span> });
    }
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.log(err);
    res.status(<span class="hljs-number">500</span>).json({
      <span class="hljs-attr">err</span>: <span class="hljs-string">"User face couldn't be authenticated. Please try again later"</span>,
    });
  }
};
</code></pre>
<p>With the main hurdle completed, we can then navigate to our application and have a seamless chat experience.</p>
<p>Additionally, as a safety measure, a rate limiter is also in place to minimize the use of brute-force techniques by malicious individuals to gain access to the chat application.</p>
<h2 id="heading-additional-information-and-tips">Additional Information and Tips</h2>
<p>The overall aim of these efforts is to achieve a more scalable and secure method of user validation. The threshold can easily be modified and tweaked to improve application accuracy. Alternatively, the <a target="_blank" href="https://aws.amazon.com/rekognition/">AWS Rekognition</a> tool can sufficiently replace the Face API tool with efficient cloud-powered models. The limitations of facial recognition can also be overcome by exploring biometric authentication, as it’s a known fact that each individual's fingerprint is unique, greatly reducing the risk of user compromise.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So far, we have walked through the process of creating an efficient multi-factor facial authentication-based tool to prevent intruder access to our chat application, ensuring and prioritizing the highest level of user privacy. Need an SDK that assures you of a seamless and secure chat experience? Try Stream.io today.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy a Node.js Application on AWS ]]>
                </title>
                <description>
                    <![CDATA[ Cloud platforms and infrastructure allow you to easily deploy and host backend services and applications. In this article, you’ll learn how to run a Node.js/Express application away from the confines of your local personal computer to make it accessi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-a-nodejs-application-on-aws/</link>
                <guid isPermaLink="false">67ed67823b8c37d192779b99</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Caddy ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 02 Apr 2025 16:36:18 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743611764466/96a89440-1c72-4ac0-861d-0ea29aeb90bf.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Cloud platforms and infrastructure allow you to easily deploy and host backend services and applications. In this article, you’ll learn how to run a Node.js/Express application away from the confines of your local personal computer to make it accessible globally on the cloud. We’ll use Amazon Web Services to do this.</p>
<p>But before we get started, here are some prerequisites for the tutorial:</p>
<ul>
<li><p>An active AWS account</p>
</li>
<li><p>Basic beginner to intermediate knowledge of Node.js and Express</p>
</li>
<li><p>Knowledge of Linux commands</p>
</li>
</ul>
<p>With that, let's get started.</p>
<h3 id="heading-expected-takeaways">Expected takeaways</h3>
<p>At the end of this guide, you should be equipped with basic knowledge of:</p>
<ul>
<li><p>AWS EC2 and other hosting mediums</p>
</li>
<li><p>Linux</p>
</li>
<li><p>Networking</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-introduction">Introduction</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-aws">How to Set Up AWS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-the-nodejs-application">How to Deploy the Node.js Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-caddy">What is Caddy?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setting-up-caddy">Setting Up Caddy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-information">Additional Information</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-introduction">Introduction</h2>
<p>Deploying backend applications on the cloud is pretty straightforward thanks to the advent of public cloud service providers like AWS.</p>
<p>You can host these applications on the cloud using several methods, depending on your application’s complexity and use cases.</p>
<p>For the AWS platform, you could deploy on:</p>
<ul>
<li><p><strong>AWS EC2 (Elastic Cloud Compute)</strong>: This option lets you deploy a virtual operating system server which serves as the backbone on which the application is hosted. It's suitable for complex monolithic backend applications.</p>
</li>
<li><p><strong>AWS Lambda</strong>: This is popularly termed AWS serverless which allows speedy execution of functions when needed. It doesn’t require consistent uptime hours. This is more suited for simple backend functions with specific use cases.</p>
</li>
</ul>
<p>For the purpose of this tutorial, we will be exploring the AWS EC2 option for deploying a Node.js application. We will also cover using a dedicated reverse proxy to give you easy access to your deployed application.</p>
<h2 id="heading-how-to-set-up-aws">How to Set Up AWS</h2>
<p>Firstly, I assume that you have an AWS account (minimum free tier). If you don't, kindly <a target="_blank" href="https://portal.aws.amazon.com/billing/signup">navigate here</a> and set up your account.</p>
<p>After you have logged in successfully, you will have access to all the various AWS products available. Search for AWS EC2 on the search bar. Once you click that, you will see the EC2 dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697716239/8020771d-3941-490b-8468-36d82e5e8c24.png" alt="EC2 dashoard" class="image--center mx-auto" width="1189" height="283" loading="lazy"></p>
<p>We’ll now create a new EC2 instance.</p>
<p>For cost-effectiveness and simplicity, we’ll use the free tier options made available by AWS. First, you’ll begin by creating an instance name. You can set this according to your preference.</p>
<p>Next, you’ll choose a specific operating system to serve as the operating system for your virtual sever. In this tutorial, I’ll be opting for the Ubuntu Linux distro.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742826868559/a08cbc5c-e35f-4264-ab17-6746dfea74d8.png" alt="Operating system images" class="image--center mx-auto" width="1140" height="480" loading="lazy"></p>
<p>Next you’ll choose a compatible compute instance type. AWS provides free access to <em>t2.micro</em> and <em>t3.micro</em> which will suffice for hosting your application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697788341/b4462135-7657-4608-a339-3a18d7187db1.png" alt="EC2 instance type" class="image--center mx-auto" width="774" height="275" loading="lazy"></p>
<p>This part allows you to configure <code>ssh</code> to enable remote access to your server. In my case, I opted out since I intend to use the EC2 connect console option.</p>
<p>After completing the steps above you’ll configure the network settings. This is where your knowledge of Networking will come in handy.</p>
<p>Automatically, AWS creates and assigns a virtual private cloud network to your soon-to-be-launched EC2 instance. You can customize it to suit your purposes, but for this tutorial, we’ll go with the default VPC assigned. Also, we’ll leave the subnet and auto-assign IP the way it is.</p>
<p>For the firewall settings, it comes with two options: create a security group or use an existing security group. For ease of use with the EC2 instance you’ll create, you can configure the Firewall setting by creating a new security group, specifying the network types, and restricting the IP address of users trying to access the EC2 instance you’ll create. Further, you still might want to use any of your preformed firewall configurations in the <em>“use existing security group</em>” option.</p>
<p>You can leave other sections as they are, and then go ahead and create your EC2 instance.</p>
<p>Once you’ve successfully created the EC2 instance, you can connect to the instance via the options provided.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697864497/40b77502-7f7b-4f76-9e8d-fbabfe3d5755.png" alt="EC2 connect options" class="image--center mx-auto" width="1184" height="561" loading="lazy"></p>
<p>For the purpose of this tutorial, you’ll use the EC2 instance connect option to access your EC2 instance. Once you’ve clicked on the button, you will then be brought into the Linux console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742826982246/5c4f67d6-11f1-4346-9c33-a3fbb969bbba.png" alt="Linux console" class="image--center mx-auto" width="1315" height="479" loading="lazy"></p>
<p>To begin, you’ll immediately update your operating system packages using the <code>sudo</code> command.</p>
<p>The <code>sudo apt update</code> command will get this done. With your packages up to date, now you can install the relevant packages needed to get your Node.js application powered on: the <em>Node.js installer package</em> and <em>npm</em> (node package manager) tools, respectively.</p>
<p>Then install them using the <code>sudo apt install nodejs npm</code> command.</p>
<p>With this done, you’ve gotten everything ready to run your application.</p>
<h3 id="heading-how-to-deploy-the-nodejs-application">How to Deploy the Node.js Application</h3>
<p>We’ll use a simple Node.js/Express application in this tutorial. You can find the source code <a target="_blank" href="https://github.com/rat9615/simple-nodejs-app">here</a>. Inside your EC2 console, clone the application source code using the <code>git clone</code> <a target="_blank" href="https://github.com/rat9615/simple-nodejs-app"><code>https://github.com/rat9615/simple-nodejs-app</code></a> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697610337/b777176a-d97e-4289-bb43-002d4b80f88c.png" alt="This image shows the application code cloning process using git" class="image--center mx-auto" width="638" height="174" loading="lazy"></p>
<p>After successfully cloning the code project, execute the command <code>cd simple-nodejs-app</code> to navigate into the code folder directory. Now, install the various necessary application dependencies that are included in the code project’s <code>package.json</code> file by executing <code>npm install</code>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697545681/8c99ae1f-8d4e-4116-944d-5ce0d7613550.png" alt="This image shows installing all the packages needed to run the backend application. The command executed is npm install" class="image--center mx-auto" width="973" height="461" loading="lazy"></p>
<p>After completing the above steps, the <code>npm start</code> command will bring your application to life. You should then see a success message on your screen.</p>
<p>But if you navigate to the EC2 instance public IP address with the Instance IP address sub-port 3000, you’ll still see an error – so what haven’t we completed?</p>
<p>Here is where your knowledge of Networking comes in again. Now, navigate back to your cloud EC2 compute dashboard and go to the security groups. These contain and enforce your inbound and outbound rules.</p>
<p>But before we go on, what are inbound and outbound rules?</p>
<ul>
<li><p><strong>Inbound rules</strong> allow you to easily configure access to the cloud resource via any route. They ensure that only those who are expressly authorized are granted access. These routes include, but are not limited to, SSH, HTTP, HTTPS, and TCP.</p>
</li>
<li><p><strong>Outbound rules</strong> allow you to easily configure the flow of cloud resources information to the external world. Only authorized Internet protocol addresses will get access to the information requested.</p>
</li>
</ul>
<p>So now, you’ll be creating a new inbound rule which will give you access to the backend API endpoint at port 3000:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743174093701/0d31d813-58cb-40d3-8559-71974aefaefd.png" alt="In this image, we are defining relevant inbound rules for our machine " class="image--center mx-auto" width="1335" height="474" loading="lazy"></p>
<p>Clicking on the Add rule button allows you to add new network access routes on your EC2 machine. Already setup are the HTTP and TCP traffic routes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743174075948/e0d6a6c9-3f7a-48bd-804b-083eb1d7514f.png" alt="This shows the various networking ports and routes on our AWS machine" class="image--center mx-auto" width="1118" height="181" loading="lazy"></p>
<p>The image above highlights all the included inbound rules in a demo application. Now let’s return to configuring our Networking settings.</p>
<p>Within the security groups in your dashboard, click on the <strong>Add rule</strong> button at the end of the page.</p>
<p>Select the TCP network type, set the host to <code>0.0.0.0.0/0</code>, and set the port to port 3000. Lastly, to complete the IP address request setup, just click on the “allow from anywhere” option. Save the rule and refresh your tab. Within a few minutes, the endpoint will be made available on port 3000.</p>
<p>To see the application live in action, click on the external IP address of the EC2 instance and add a suffix port 3000 to view the backend application interface. And violà, your application should now be live.</p>
<p>But that’s not all – it's inconvenient to include the sub-port number while browsing the IP address. So you’ll need a compatible effective reverse proxy tool which routes any information from port 3000 to port 80 (which is a general port). A reverse proxy in this scenario routes and forwards requests from clients to a server serving as a protective intermediary. To do this, you can use a tool called Caddy.</p>
<h2 id="heading-what-is-caddy">What is Caddy?</h2>
<p>Caddy is a flexible, beginner-friendly, open-source tool which offers reverse proxy, load balancing, and caching features in addition to its role as a web server. It has an extensive user guide and documentation which you can lookup <a target="_blank" href="https://caddyserver.com/docs/">here</a>.</p>
<p>Now, let’s set up Caddy on your EC2 instance.</p>
<h2 id="heading-setting-up-caddy">Setting up Caddy</h2>
<h3 id="heading-install-caddy">Install Caddy</h3>
<p>First, you’ll need to install Caddy on your Linux OS. You can do this by executing <code>sudo apt install caddy</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697469605/cf58d75f-ed72-4078-8e45-30b7da0916b1.png" alt="Caddy tool installation process" class="image--center mx-auto" width="656" height="422" loading="lazy"></p>
<p>After completing the installation process, the above image should be what you should see on your screen. Once you’ve done this, make sure that Caddy is enabled and powered on by running this command:</p>
<p><code>caddy run</code></p>
<p>After running the command above, the Caddy tool should be enabled and active. Then you should see the below image on your screen:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697342473/be0499f4-6a0f-406b-87d9-0688e56d8783.png" alt="Current status of the Caddy tool " class="image--center mx-auto" width="1076" height="423" loading="lazy"></p>
<p>Next, navigate to the external IP address available on your EC2 instance. There, displayed on the screen, should be the Caddy home page.</p>
<h3 id="heading-configure-caddy">Configure Caddy</h3>
<p>Going back to your console, you’ll need to tweak the Caddy configuration file to enable the reverse proxy of <strong>port 3000</strong> to the default port <strong>80</strong>.</p>
<p>To access the config file, navigate to the file from the route directory via the <code>cd /etc/caddy/Caddyfile</code> command.</p>
<p>You can then use the <code>sudo nano</code> command to open the config file for editing. The <code>sudo</code> prefix gives you admin privileges that allow you to make necessary changes on the config file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742697233724/cf694df5-74bc-4975-b3e7-c0414fb68646.png" alt="Caddy configuration file" class="image--center mx-auto" width="1160" height="458" loading="lazy"></p>
<p>Within the port 80 section in the config file, add this line of code:</p>
<p><code>reverse_proxy :3000</code></p>
<p>Save the file – and now you’re done. You can restart the Caddy tool to reflect the new settings by running <code>sudo systemctl restart caddy.</code> Refreshing the IP address will display your powered-on Node.js application. With this, you’ve successfully hosted your Node.js application on EC2 and utilized a reverse proxy tool to bring it to life.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742827013554/f99be1e5-bfc6-444c-b620-9c47ae43dc3a.png" alt="Project's Home page" class="image--center mx-auto" width="687" height="187" loading="lazy"></p>
<h2 id="heading-additional-information">Additional Information</h2>
<p>Going forward, it's good practice to enable DNS features with domain name customization, as users may not always remember the IP address. You can also further increase your expertise in deploying backend applications by experimenting with powering backend functions with AWS lambda.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. I hope you’ve learned about AWS operations and setting up a backend application on the cloud. You can also reach out to me on my blog and check out my other articles <a target="_blank" href="http://portfolio-oluwatobi.netlify.app">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Containerize a Node.js Application Using Docker – A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Over the years, applications and tools have become more complex to keep up with people’s changing requirements and expectations. But this can create issues of code compatibility and remote access. For example, a codebase that functions properly on Wi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/containerize-a-nodejs-application-using-docker/</link>
                <guid isPermaLink="false">6793a775498f1e108e0ba05d</guid>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dockerfile ]]>
                    </category>
                
                    <category>
                        <![CDATA[ containers ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Fri, 24 Jan 2025 14:45:09 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737681497302/0540f730-f1c3-496c-bd47-912fdc95d468.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Over the years, applications and tools have become more complex to keep up with people’s changing requirements and expectations. But this can create issues of code compatibility and remote access. For example, a codebase that functions properly on Windows may develop compatibility errors when installed on Linux.</p>
<p>Fortunately, Docker comes to the rescue. But you might be wondering – what is Docker, and how does it help? You’ll learn all this and more in this tutorial.</p>
<p>But before we start, here are some prerequisites:</p>
<ul>
<li><p>Knowledge of Linux commands</p>
</li>
<li><p>Knowledge of terminal usage</p>
</li>
<li><p>Knowledge of Node.js and Express.js</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-docker">What is Docker?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-docker">How to Install Docker</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demo-project-how-to-containerize-a-nodejs-application">Demo Project: How to Containerize a Node.js Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ol>
<h2 id="heading-what-is-docker">What is Docker?</h2>
<p>Docker is an open-source tool that makes it easy to run software in a consistent way, no matter where you are. It does this by putting your application and everything it needs (like libraries and settings) into a container (which I’ll discuss more in a moment).</p>
<p>Think of a container like a box: it holds your app and all its parts, so it works exactly the same on your laptop, a server, or in the cloud. Docker helps developers avoid the "it works on my machine" problem by ensuring everything is packaged together in a reliable and portable way.</p>
<p>Docker was created by Solomon Hykes in 2013. Over the years, it has evolved to cover a wide range of tools. It’s become a go-to tool for improving the application deployment and networking processes.</p>
<p>Before we proceed, here are some key terms you will come across as we go through this tutorial:</p>
<h3 id="heading-docker-engine"><strong>Docker Engine</strong></h3>
<p>The Docker engine, as its name implies, is the powerhouse for Docker applications. It has a client and a server component. The Docker client, in our case, is the command-line interface tool or Docker terminal we’ll be using to send relevant commands for project execution. The Docker server, popularly known as the daemon, is the server that handles running the various Docker images and containers.</p>
<h3 id="heading-docker-image"><strong>Docker Image</strong></h3>
<p>Docker images are premade templates of executable software and systems. Docker offers a wide range of images ranging from operating system templates to server templates, software templates, and so on. You can find all these on the Docker hub registry where these images are stored.</p>
<p>You can also build a specific image and host it either publicly on the Docker hub or in a private registry.</p>
<h3 id="heading-docker-containers"><strong>Docker Containers</strong></h3>
<p>Docker containers are executable compact instances built on the template generated which is the Docker image. They’re lightweight, portable packages that include everything needed to run a piece of software—code, runtime, libraries, and system tools. A container ensures the application runs consistently regardless of the environment.</p>
<h3 id="heading-benefits-of-using-docker">Benefits of Using Docker</h3>
<p>Here are some of the benefits of using Docker as a backend developer:</p>
<ul>
<li><p>Docker is a great tool for creating a solid DevOps culture for application development, as it clarifies the functions of the development and operations teams.</p>
</li>
<li><p>It’s also quite flexible, allowing for easy deployment of microservices and distributed monolithic backend applications.</p>
</li>
<li><p>It also minimizes errors from dependency misconfigurations during installations as it ports the app with its necessary dependencies all at once.</p>
</li>
</ul>
<p>Moving on, we will be diving into how to Dockerize a Node.JS Express application. But before that, you’ll need to install Docker on your computer. You can skip this if you already have it installed.</p>
<h2 id="heading-how-to-install-docker">How to Install Docker</h2>
<p>Docker is a cross-platform tool which can be installed across all popular operating systems (Windows, Mac OS, and Linux distros). For this tutorial, I’ll only be highlighting how to set up Docker on Windows.</p>
<p>If you’re currently using any OS other than Windows, you can easily set Docker up by following the steps in the Docker documentation <a target="_blank" href="https://docs.docker.com/engine/install/">here</a>.</p>
<p>For windows users, it is essential that your PC meets the minimum specifications – otherwise the installation won't be successful. The minimum requirements are the following:</p>
<ul>
<li><p>A Windows OS version not less than Windows 10 home</p>
</li>
<li><p>A PC with WSL-2 installed or Hypervisor enabled.</p>
</li>
</ul>
<p>With that, let's move on to downloading the Docker installer executable. You can download the latest Docker installer from <a target="_blank" href="https://www.docker.com/products/docker-desktop/">here</a>. After you do that, run the software and accept the terms and conditions. On successful completion, launch the application. This is what you should see:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737154696376/dcbf3b23-10cc-452a-b206-46973163e8d6.png" alt="Docker desktop GUI" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>To confirm that you’ve successfully installed the application, navigate to the command prompt terminal and run <code>Docker –-version</code>. You should see the exact version of the Docker engine tool you’ve installed if it was successful.</p>
<p>We’ll now move on to the project proper.</p>
<h2 id="heading-demo-project-how-to-containerize-a-nodejs-application">Demo Project: How to Containerize a Node.js Application</h2>
<p>In this section, we will be containerizing a simple Node.js-based backend service with minimal dependencies. This will show you how to containerize and port an application using a Docker application containerization technique known as the <strong>Dockerfile</strong>. Keep in mind that if you have a more complex application, it may be better to use the <a target="_blank" href="https://www.freecodecamp.org/news/what-is-docker-compose-how-to-use-it/"><strong>Docker compose YAML tool</strong></a>.</p>
<p>To begin with, we will set up the sample Node.js application. I’ll provide the entire code setup in this article, below. But first, let’s understand what a <strong>dockerfile</strong> is.</p>
<h3 id="heading-what-is-a-dockerfile">What is a Dockerfile?</h3>
<p>Basically, a Dockerfile is a template system which allows the user to input commands which, when executed, can produce a functional image of the application. This image can then be converted into a container.</p>
<p>Here are some commands included in the basic structure of a Dockerfile:</p>
<ul>
<li><p><code>CMD</code><strong>:</strong> sets the default command to run if no command is specified when the container starts. It can be overridden by providing a command when running the container (<code>docker run ...</code>).</p>
</li>
<li><p><code>ENTRYPOINT</code><strong>:</strong> Specifies the main command that always runs when the container starts. It’s not easily overridden, but arguments can be appended.<br>  <strong>Note</strong> that <code>CMD</code> and <code>ENTRYPOINT</code> both specify what command or process the container should run when it starts. But they’re used differently and have distinct purposes. Use <code>CMD</code> for default behavior that can be overridden. Use <code>ENTRYPOINT</code> for a fixed command that defines the container's primary purpose.</p>
</li>
<li><p><code>FROM</code><strong>:</strong> This is usually the opening statement in a Dockerfile. This command fetches a base image which forms the foundation for building the image of the application in question. For instance, in our application, the base image for a Node.js application is to have the baseline Node.js engine installed.</p>
</li>
<li><p><code>WORKDIR</code><strong>:</strong> This syntax defines the active working directory where the application files will live within the defined container. An automatic folder will be created if it’s not already available.</p>
</li>
<li><p><code>COPY</code><strong>:</strong> This syntax is used to ensure that the files necessary for creating the Docker image from the code base project file are copied into the newly created Docker container. The directories of these files are carefully highlighted.</p>
</li>
<li><p><code>RUN</code><strong>:</strong> This syntax specifies the script that you want to be run before completing the application’s containerization.</p>
</li>
<li><p><code>ENV</code><strong>:</strong> This syntax is used to highlight environmental variables and secrets which will be invoked during the process of running the application.</p>
</li>
<li><p><code>EXPOSE</code><strong>:</strong> This syntax maps out the browsing port where the application is used to communicate with the external internet. For example <code>EXPOSE: 3000</code> maps out the application web interface to <code>localhost:3000</code>.</p>
</li>
</ul>
<p>Diving deeper into Docker, let’s quickly go over some key Docker commands we’ll be using throughout this tutorial:</p>
<ul>
<li><p><code>Docker ps</code><strong>:</strong> This command lists all the running containers on your Docker terminal.</p>
</li>
<li><p><code>Docker run</code><strong>:</strong> This command executes a Docker image to trigger an instance of a container.</p>
</li>
<li><p><code>Docker build</code><strong>:</strong> This command works based on the Docker file to generate an image of a service or application.</p>
</li>
<li><p><code>Docker rm</code><strong>:</strong> this command can be used to delete an image using the image identification details.</p>
</li>
</ul>
<h3 id="heading-how-to-containerize-the-app">How to Containerize the App</h3>
<p>Now we can start containerizing our simple Node/Express application. To follow along with the tutorial, you can get the base code from <a target="_blank" href="https://github.com/oluwatobi2001/Typescript_test">here</a>.</p>
<p>On testing it locally, it returns a CRUD API where you can create, fetch, update, and delete products when executed. We’ll package the application for easy deployment on the cloud using our Docker engine. We’ll be able to do this using the Dockerfile tool we discussed above.</p>
<h4 id="heading-step-1-create-the-dockerfile">Step 1: Create the dockerfile</h4>
<p>In your project folder, create a file named <code>Dockerfile</code>. Make sure the name is <strong>exactly</strong> "Dockerfile" (no extension, and case-sensitive in some systems – so make sure it’s capitalized).</p>
<p>If you're using a code editor, simply create a new file named <code>Dockerfile</code>. If you're using a basic text editor, save the file with the name <code>Dockerfile</code> and ensure it doesn’t accidentally save with an extension like <code>.txt</code>.</p>
<p>Then enter the first line:</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> Node:<span class="hljs-number">18</span>-alpine
</code></pre>
<p>This command fetches the base image we’ll use to power our Express application which is the Node engine itself.</p>
<p>You might be wondering what the <code>alpine</code> is for. Alpine is a lightweight, much more compressed version of a Docker image. It excludes incorporating additional packages not directly essential to the base operating system. It's advocated as a standard good code practice to use lightweight distros for faster execution and easy use.</p>
<h4 id="heading-step-2-set-the-working-directory">Step 2: Set the working directory</h4>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>
</code></pre>
<p>This sets the working directory of the image to the <code>/app</code> folder of the container. It makes sure that all file actions occur here and all files are copied into this directory.</p>
<h4 id="heading-step-3-copy-the-necessary-files">Step 3: Copy the necessary files</h4>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">COPY</span><span class="bash"> package.json</span>
</code></pre>
<p>This command copies the <code>package.json</code> files which has a list of dependences and packages to be installed to power our application.</p>
<h4 id="heading-step-4-execute-a-setup-script">Step 4: Execute a setup script</h4>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">RUN</span><span class="bash"> npm install</span>
</code></pre>
<p>This command ensures that all the necessary dependencies to power our Node.js applications are installed on the container.</p>
<h4 id="heading-step-5-copy-the-code-files">Step 5: Copy the code files</h4>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">COPY</span><span class="bash"> . .</span>
</code></pre>
<p>This command ensures that all the files within the local directory get copied into the container file system within the established working directory.</p>
<h4 id="heading-step-6-expose-the-server-port">Step 6: Expose the server port</h4>
<pre><code class="lang-dockerfile">

<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">3000</span>
</code></pre>
<p>This command exposes the server port that we intend to use to access the container. In this case it's port 3000.</p>
<h4 id="heading-step-7-include-the-command-to-bring-the-container-to-life">Step 7: Include the command to bring the container to life</h4>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"npm"</span>, <span class="hljs-string">"run"</span>, <span class="hljs-string">"dev"</span>]4</span>
</code></pre>
<p>This command is executed a the end in order to power on the Node.js application. It simply runs the <code>npm run dev</code> command which is what you’d use for a development environment. To run it in a production environment, you’d use the <code>npm start</code> command instead.</p>
<p>Having completed this process, here is how the final Dockerfile structure should look:</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> Node:<span class="hljs-number">18</span>-alpine
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-keyword">COPY</span><span class="bash"> package.json</span>

<span class="hljs-keyword">RUN</span><span class="bash"> npm install</span>

<span class="hljs-keyword">COPY</span><span class="bash"> . .</span>

<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"npm"</span>, <span class="hljs-string">"run"</span>, <span class="hljs-string">"dev"</span>]</span>
</code></pre>
<h3 id="heading-testing-the-docker-container">Testing the Docker container</h3>
<p>To round it up, we will be creating a Docker image of our Node.js application. To do this, execute the command <code>docker build -t nodeapp .</code> . The <code>docker build</code> command builds the image, while the <code>-t</code> allows for specifying the image tag’s details.</p>
<p>In our case, we’re assigning the name <code>nodeapp</code> to the image we will be creating and the image will be created within the working directory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737154702142/98e05981-bb05-41c6-919f-02b3261f3caa.png" alt="This image runs the docker build command" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Congratulations! You have successfully built your first Docker image. To see all the images on your local repo, execute the command <code>docker images</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737154714828/71f50b4f-8df5-4885-a5fc-6365dd903645.png" alt="A image showing the docker images command being executed and the list of all the images available locally" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In order to create a working instance of your image for testing, execute the command <code>docker run nodeapp</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737154708130/bb6968f2-829d-4107-be82-4bdd9c167d53.png" alt="Executing a running instance of our docker image" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We’re using Mongo DB as our database for this tutorial, so we’ll need to pass the MongoDB URL as an environment variable to the Docker container. Environment variables help you safeguard certain key variables which shouldn’t be exposed to the public. Other variables which can be passed as environment variables include API keys and encryption codes.</p>
<p>To pass the MongoDB URL to the Docker container, we use the <code>-e</code> tag to ensure that Docker recognizes the corresponding value inputted as an environment variable.</p>
<p><code>docker run -e JWT_SECRETS={enter the value of your choice} -e MONGO_URL={The mongo url of your choice} nodeapp</code>.</p>
<p>To also use the container in the background, just attach the <code>-d</code> tag which represents the detach option. This option allows the container to run in the background despite exiting the command line terminal.</p>
<p>In the event of no errors, navigating to <code>localhost:5000</code> should also produce something similar to the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737506281699/54bb1d9b-0be7-42e3-b212-bb4bd27e019d.png" alt="Postman testing the localhost:5000 " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this article, you learned about what Docker is and how it works, along with its common commands and how to use it to containerize a backend application. Moving on from the basics, you can also explore other uses of Docker in continuous integration and development. To learn more about Docker, you can check out its documentation <a target="_blank" href="https://docs.docker.com/">here</a>.</p>
<p>I would also recommend using your new knowledge to deploy projects with real-life use cases, as well as exploring networking in Docker applications. To make your app live, you can easily deploy the Docker image you created to any of the popular cloud service providers like AWS, GCP, Azure, and so on.</p>
<p>Feel free to ask me any questions! You can also check out my other articles <a target="_blank" href="http://portfolio-121.netlify.app">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Beginner's Guide to Terraform – Infrastructure-as-Code in Practice ]]>
                </title>
                <description>
                    <![CDATA[ Over the years, cloud development has seen a major paradigm shift. Newer and more complex applications are deployed rapidly to the cloud to minimize downtime. And through all of this, the concept of Infrastructure-as-Code and various tools have emerg... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-beginners-guide-to-terraform-infrastructure-as-code-in-practice/</link>
                <guid isPermaLink="false">67782a8fd3a89d514105e418</guid>
                
                    <category>
                        <![CDATA[ Terraform ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Infrastructure as code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Terraweekchallenge ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Fri, 03 Jan 2025 18:21:03 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735900327439/09832fb8-8cc0-4182-b70a-5f54ee6fce7d.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Over the years, cloud development has seen a major paradigm shift. Newer and more complex applications are deployed rapidly to the cloud to minimize downtime. And through all of this, the concept of Infrastructure-as-Code and various tools have emerged to simplify the process of application development.</p>
<p>You might be wondering: what is Infrastructure-as-Code? How does it improve the development process and experience, and where does Terraform come into the picture? Well, we’ll explore all this and more in this guide. But before we start, here are some pre-requisites:</p>
<ul>
<li><p>Basic knowledge of the cloud and cloud terminologies</p>
</li>
<li><p>Access to a PC to implement code examples</p>
</li>
<li><p>A GCP account</p>
</li>
</ul>
<p>With this, let's get started.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-overview-of-infrastructure-as-code-iac">Overview of Infrastructure as Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-terraform">What is Terraform?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-terraform">Benefits of Terraform</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-terms-used-in-terraform">Common Terms Used in Terraform</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demo-project-how-to-write-a-terraform-configuration">Demo Project: How to Write a Terraform Configuration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-overview-of-infrastructure-as-code-iac">Overview of Infrastructure as Code (IaC)</h2>
<p>Infrastructure as code refers to generating cloud infrastructure tools and applications with a code-based configuration document. This process, when running, automates the sequence and process of creating databases, virtual machines, and servers. This improves the user experience by reducing the frequency of manual cloud service deployments, especially for multiple identical services.</p>
<p>There are two distinct approaches to infrastructure as code: the <code>Imperative</code> approach and the <code>Declarative</code> approach.</p>
<p>When you’re using the Declarative approach to infrastructure generation, you simply detail your expected/desired outputs for the Infrastructure to be generated, and then the IaC tool you’re using figures out how to produce that output.</p>
<p>On the other hand, the Imperative approach involves specifying the exact steps needed to achieve the desired infrastructure state. While the Imperative approach seems more suited for complex infrastructure setups, the Declarative approach can work just as well. </p>
<p>Some tools are capable of both approaches while others are only suited to one or the other. Examples of some of the popular IaC tools used globally include <a target="_blank" href="https://www.terraform.io/">Terraform IaC</a>, <a target="_blank" href="https://aws.amazon.com/cloudformation/">AWS Cloud Formation</a>, <a target="_blank" href="https://www.redhat.com/en/ansible-collaborative">Ansible</a>, and <a target="_blank" href="https://www.pulumi.com/">Pulumi</a>, <a target="_blank" href="https://www.chef.io/glossary/what-is-infrastructure-as-code">Chef</a>, among others.</p>
<p>Like the name implies – infrastructure as <strong>code</strong> – the code creating the infrastructure is written in various template languages within the IaC space. Popular template languages include JSON, YAML, ARM template, HCL, Heat Scripts, and so on.</p>
<p>You can also use scripting tools to execute cloud infrastructure. Some popular ones include Bash and PowerShell. These sometimes come preinstalled on most personal computers.</p>
<p>Out of all these tools, though, Terraform is distinct for various reasons – and it’s the one we’ll be examining in this article.</p>
<h2 id="heading-what-is-terraform">What is Terraform?</h2>
<p>Terraform is an open source tool developed by HashiCorp in 2014. It has evolved over the years and now serves as a cloud agnostic infrastructure tool that allows you to create infrastructure across multiple cloud service providers.</p>
<p>Terraform also offers <a target="_blank" href="https://app.terraform.io/session">Terraform Cloud</a>, a cloud-based software as a service tool. It allows for cloud-based deployment of cloud tools, instead of using the old local-based methods we had in the defunct Terraform CLI tool.</p>
<p>Also, like other IaC tools which utilize template languages, the template framework used to create infrastructure in Terraform is the HashiCorp template language (HCL).</p>
<h2 id="heading-benefits-of-terraform">Benefits of Terraform</h2>
<p>Now I’ll highlight some of the benefits of using Terraform as a cloud engineer, along with the tool’s key role in the cloud ecosystem.</p>
<h3 id="heading-1-declarative-approach"><strong>1. Declarative Approach</strong></h3>
<p>This approach to cloud infrastructure automation ensures that all required infrastructure to be deployed (databases, servers, and so on) is stated explicitly and executed accordingly. This helps avoid conflicts.</p>
<h3 id="heading-2-conflict-handling"><strong>2. Conflict Handling</strong></h3>
<p>In addition to its efficient cloud tool automation capabilities, Terraform has some robust conflict detection and handling properties. One of the ways it handles conflicts is via the <code>Terraform plan</code> function. This function highlights any perceived or potential conflicts of infrastructure orchestration which allows for easy correction before deployment. I’ll discuss this further in subsequent sections.</p>
<h3 id="heading-3-cloud-agnostic"><strong>3. Cloud Agnostic</strong></h3>
<p>Terraform is a multipurpose, multi-cloud automation service provider with efficient infrastructure automation capabilities across the major cloud service providers (AWS, GCP and Azure). It also allows for hybrid and inter-provider automation.</p>
<h3 id="heading-4-user-friendly"><strong>4. User-friendly</strong></h3>
<p>Terraform is one of the largest cloud automation tools with the largest user communities out there. It has extensive beginner-friendly tutorials that help you get a quick hang of the tool. Here is a link to its <a target="_blank" href="https://developer.hashicorp.com/terraform/docs">documentation</a> so you can dive in deeper.</p>
<h3 id="heading-5-file-management-capabilities"><strong>5. File Management Capabilities</strong></h3>
<p>Terraform automatically creates a local backup of the automation states on your local computer to ensure immediate recall and file handling in case anything goes wrong. It also offers remote backup options to remote cloud service providers where necessary.</p>
<h3 id="heading-6-version-control"><strong>6. Version Control</strong></h3>
<p>Just like the Git version control system, Terraform has a built-in version control system which lets you track changes to a Terraform file. It also lets you go back to previous versions of your code if there are errors in the present version, for example.</p>
<h3 id="heading-7-code-reusability"><strong>7. Code Reusability</strong></h3>
<p>Terraform offers a wide variety of code templates for easy reuse on its developer documentation page.</p>
<p>Now that we’ve highlighted the benefits of Terraform, let’s learn some common terminologies used in Terraform and what they mean.</p>
<h2 id="heading-common-terms-used-in-terraform">Common Terms Used in Terraform</h2>
<p>Before you start using Terraform, you should be familiar with some key terms that come up a lot. Here’s what you need to know:</p>
<ol>
<li><p><strong>Providers</strong>: in Terraform, a Provider is a programming interface that lets Terraform interact with various APIs and cloud services. For example, you’d use a provider to interface with a cloud service provider like GCP or Azure.</p>
</li>
<li><p><strong>Modules:</strong> Modules are specifically created within the Terraform framework and serve as reusable components that let you easily orchestrate cloud services. You can also store key information regarding cloud services in a module, and then modify it to ensure uniqueness using module variables.</p>
</li>
<li><p><strong>Resources:</strong> Resources in Terraform refer to the cloud infrastructure components to be created. Examples include cloud networks, virtual machines, availability zones, and other infrastructures.</p>
</li>
<li><p><strong>State:</strong> The concept of state in Terraform forms the basis for its efficiency. State keeps track of the current configuration of your infrastructure resources, and contains details about every resource Terraform has created, modified, or deleted. Terraforms version control system uses it to track any changes you make to a code file and uses that information to destroy and provision infrastructure as necessary.</p>
</li>
<li><p><strong>Workspace:</strong> a Workspace functions sort of similarly to a version control system, as it creates a sort of constraint around a work file. Workspaces let you manage multiple instances of a single infrastructure configuration in a clean and isolated way within the same backend. You can use workspaces to separate environments like development, staging, and production while using the same Terraform configuration.</p>
</li>
</ol>
<h2 id="heading-demo-project-how-to-write-a-terraform-configuration">Demo Project: How to Write a Terraform Configuration</h2>
<p>In this section, we’ll be diving deeper into writing our first Terraform file to orchestrate a Google Cloud program virtual machine with just a few lines of code. But before we begin, we’ll discuss the various commands that you should understand before we implement the demo project.</p>
<h3 id="heading-common-terraform-commands">Common Terraform Commands</h3>
<ul>
<li><p><code>Terraform init</code><strong>:</strong> This command initializes the Terraform tool and downloads essential cloud provider-specific files. It also establishes a connection between Terraform and the cloud provider in question. In our case, it’s between GCP and the Terraform provider.</p>
</li>
<li><p><code>Terraform fmt</code><strong>:</strong> This command automatically ensures optimal code formatting and indentation. It ensures orderly execution of the code and minimizes any errors.</p>
</li>
<li><p><code>Terraform plan</code><strong>:</strong> This command outlines the steps of execution of the Terraform code, and detects any errors that may occur during the process of execution. It also highlights any errors in the Terraform code that may hinder execution. Lastly, it works alongside Terraform state management to detect any change of state and de-provision or generate any additional cloud services if necessary.</p>
</li>
<li><p><code>Terraform apply</code><strong>:</strong> This command executes the planned Terraform state implemented by the <code>Terraform plan</code> command.</p>
</li>
<li><p><code>Terraform destroy</code><strong>:</strong> This command is the final command in the Terraform scheme which is used to deactivate or destroy all the cloud services created using the Terraform apply command. It's important to note that you should execute the commands listed above sequentially to ensure that your infrastructure gets created properly.</p>
</li>
</ul>
<h3 id="heading-creating-an-iac-powered-gcp-virtual-machine">Creating an IaC-Powered GCP Virtual Machine</h3>
<p>Now that you’ve learned these important commands, let’s test them all out by creating our first-ever IaC-powered GCP virtual machine.</p>
<p>In your code editor, type the following code:</p>
<pre><code class="lang-plaintext">provider "google" {
  project = "your-gcp-project-id"  # Replace with your GCP Project ID
  region  = "us-central1"          
  zone    = "us-central1-a"        
}
</code></pre>
<p>This code highlights the cloud provider we’re using to generate the cloud resources we need. In our case, it’s the Google cloud program. The name assigned to it is just “google”. Other cloud providers like AWS and Azure are “aws” and “azure” respectively.</p>
<p>The second line identifies the GCP subscription identifier, which is unique to each GCP account (and helps facilitate accurate integration). <strong>You should use yours in the space provided.</strong></p>
<p>You’ll also need to include a suitable resource region and resource availability zone. This serves as the physical base for the virtual machine we’ll create so we can run it. In this scenario, I chose the USA central region and 1-a availability zone, respectively. You can read more <a target="_blank" href="https://cloud.google.com/compute/docs/regions-zones">here</a> about cloud regions and availability zones.</p>
<pre><code class="lang-plaintext">resource "google_compute_instance" "vm_instance" {
  name         = "example-vm"      
  machine_type = "e2-medium"          

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11" 
    }
  }
</code></pre>
<p>The code snippet above specifies the exact compute resource that’ll be orchestrated, which in our case is a virtual machine instance coded as “vm_instance”. <code>'example-vm’</code> is the name we want to assign to the virtual machine we will be creating for this project. It is important to note that the virtual machine name must be unique too. The type of the virtual machine we opted for was the E2 (General purpose)-medium type VM. You can get more information on Virtual machine types <a target="_blank" href="https://cloud.google.com/compute/docs/general-purpose-machines">here</a>.</p>
<p>Going further, we also specify the expected booted Operating system (“boot_disk”) which is an image of the Debian Linux Operating system version 11 in my case.</p>
<pre><code class="lang-plaintext">  network_interface {
    network = "default"  # Attach to the default VPC network
    access_config {

    }
  }

output "instance_ip" {
  value = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
}
</code></pre>
<p>To complete the creation of our virtual machine, we need to set up a Virtual Network to allow remote access to the VM. The network interface block connects the virtual machine to the default VPC (Virtual Private Cloud) network provided by GCP. We won’t be able to interface with our virtual machine without the VPC network. The output block also displays the default access IP address in the terminal, which we can use to connect to the virtual machine.</p>
<p>Here is the final expected code:</p>
<pre><code class="lang-plaintext">
provider "google" {
  project = "your-gcp-project-id"  # Replace with your GCP Project ID
  region  = "us-central1"          
  zone    = "us-central1-a"       
}

resource "google_compute_instance" "vm_instance" {
  name         = "example-vm"         
  machine_type = "e2-medium"          

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"  
    }
  }

  network_interface {
    network = "default"  # Attach to the default VPC network
    access_config {

    }
  }

output "instance_ip" {
  value = google_compute_instance.vm_instance.network_interface[0].access_config[0].nat_ip
}
</code></pre>
<p>Going on from there, we’ll now be executing this code using the commands highlighted in the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734796321588/29561c5c-3908-43d1-8579-53a3de33358a.png" alt="29561c5c-3908-43d1-8579-53a3de33358a" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The command <code>terraform -v</code> confirms that Terraform has been successfully installed on the terminal. The expected output will be the version of the Terraform tool installed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734796340539/149f5f24-90eb-4777-8ae3-18acdd3c758a.png" alt="149f5f24-90eb-4777-8ae3-18acdd3c758a" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The next command executed is the <code>terraform init</code> function which initializes a communication with the cloud service provider, which in our case is GCP. All needed dependencies are also installed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734796301342/bd886728-dfdb-49f7-bcbf-1e53ff203b35.png" alt="bd886728-dfdb-49f7-bcbf-1e53ff203b35" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The <code>terraform fmt</code> command is also run to ensure adequate code formatting and indentation. Then the <code>terraform plan</code> command is sequentially executed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734889731467/bb454ec4-47e4-40a4-84fc-91c580fb77bb.png" alt="bb454ec4-47e4-40a4-84fc-91c580fb77bb" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>From the image above, you can see the steps Terraform intends to use to generate the expected Virtual machine.</p>
<p>On successful execution of Terraform plan, we will then execute the <code>terraform apply</code> function to execute the steps outlined by Terraform plan.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734796355772/d1d8f9f9-98a9-4ab0-be00-60a9b2b993a9.png" alt="d1d8f9f9-98a9-4ab0-be00-60a9b2b993a9" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This will generate a prompt asking for a confirmation of the Terraform execution as shown above. Typing “Yes” will allow the operation to proceed smoothly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734796361770/a08254b0-878a-4681-b6ce-f6b0a9a83bc6.png" alt="a08254b0-878a-4681-b6ce-f6b0a9a83bc6" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>On successful execution, a success message will be displayed as shown above. With that, we have created our Cloud infrastructure with just code. The <code>terraform destroy</code> command can then be called to remove the created Virtual machines.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you’ve learned the basics about infrastructure as code. We discussed Terraform, its benefits, and some of its key features and commands. We also illustrated its use in a demo project.</p>
<p>To further enhance your knowledge, you can <a target="_blank" href="https://developer.hashicorp.com/terraform?product_intent=terraform">consult Terraform‘s documentation</a> for more code examples. I would also recommend utilizing your newly gained knowledge to automate a project with real-life uses.</p>
<p>Feel free to message me with any comments or questions. You can also check out my other articles <a target="_blank" href="http://portfolio-oluwatobi.netlify.app">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Object Relational Mapping in Node.js – Optimize Database Interactions With Sequelize ORM ]]>
                </title>
                <description>
                    <![CDATA[ Databases play a vital role in the development of applications across mobile and web platforms. Adequate knowledge of data interactions between the application structure and the database is essential for storing relevant application data. Object-rela... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/object-relational-mapping-in-nodejs-with-sequelize-orm/</link>
                <guid isPermaLink="false">670fa2e2c038b5fdec128d46</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Object Oriented Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 16 Oct 2024 11:26:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728644693143/667b7624-6dc2-407a-828b-f5b6c1844ac8.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Databases play a vital role in the development of applications across mobile and web platforms. Adequate knowledge of data interactions between the application structure and the database is essential for storing relevant application data.</p>
<p>Object-relational mapping, as a programming concept, is an efficient standard protocol for facilitating seamless connection with databases. But what does it really mean, and how do you set it up as a developer? We’ll answer these questions and highlight more about object-relational mapping.</p>
<p>Here are the prerequisites:</p>
<ul>
<li><p>Knowledge of Node.js</p>
</li>
<li><p>Use the Express framework</p>
</li>
<li><p>An installed MySQL database</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-table-of-contents">Table of Contents</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-an-orm">What is an ORM?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-nodejs-server">How to Set Up Your Node.js Server</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-relevant-packages">How to Integrate Relevant Packages</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demo-project">Demo Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-information">Additional Information</a></p>
</li>
</ul>
<h2 id="heading-what-is-an-orm">What is an ORM?</h2>
<p>Object Relational Mapping (ORM) is a database communication concept in programming that involves the abstraction of data types as compatible object-oriented programming variables. It simply eliminates the use of database-defined queries and storage types to allow ease of creating databases via the programming languages.</p>
<p>Its use has been widely adopted in the tech space as has more advantages than conventional database query methods. Here are some of them:</p>
<ul>
<li><p>It reduces the risk of data manipulation: SQL and non-SQL injections involve inputting malicious SQL syntaxes and queries into the database, which can compromise database security. Having an ORM in place adds an input validation scheme feature, and details the expected input variable syntax and processes it accordingly.</p>
</li>
<li><p>Ease of database communication: ORM serves to simplify the use of databases as a data tool without undergoing the process of learning a different database query language. The ORM schema can be highlighted in an object-oriented fashion in the application language and can be configured to automatically translate the code to queries compatible with the database.</p>
</li>
<li><p>This feature also allows easy code portability, achieving maintenance of a single database integration code base while changing the database without any adverse outcome. It is highly flexible and can be used in any database of choice.</p>
</li>
<li><p>It also has additional features included to allow database interactions. Database migration features and version control processes are provided. With these, we have seen some of its benefits, we will then highlight popular ORM tools used globally.</p>
</li>
</ul>
<p>Here are the popular ORM tools:</p>
<ul>
<li><p><a target="_blank" href="https://docs.sqlalchemy.org/">SQLAlchemy</a></p>
</li>
<li><p><a target="_blank" href="https://www.prisma.io/">Prisma ORM</a></p>
</li>
<li><p><a target="_blank" href="https://sequelize.org/">Sequelize</a></p>
</li>
<li><p><a target="_blank" href="https://guides.rubyonrails.org/active_record_basics.html">ActiveRecord</a></p>
</li>
<li><p><a target="_blank" href="https://typeorm.io/">TypeORM</a></p>
</li>
<li><p><a target="_blank" href="https://sailsjs.com/documentation/reference/waterline-orm">Waterline</a></p>
</li>
</ul>
<p>For this article, we’ll be streamlining our ORM use cases to a basic Node.js project linked to a MySQL database. We’ll use the Sequelize ORM as the tool of choice.</p>
<p>With an average package download of 8.5 million monthly and an active development community, Sequelize boasts robust features that seamlessly integrate databases with backend applications. It also provides a user oriented documentation which helps guide the user on setting up and using the tool.</p>
<p>Here is a link to <a target="_blank" href="https://sequelize.org/docs/v6/getting-started/">the documentation</a>. It also offers support for MySQL, DB2, and SQLite Microsoft SQL server, and it offers features such as read replication, lazy loading, and efficient database transaction properties.</p>
<p>Next, we’ll set up our web application and install Sequelize to connect us to a MySQL database hosted locally.</p>
<h2 id="heading-how-to-set-up-your-nodejs-server">How to Set Up Your Node.js Server</h2>
<p>In this section you’ll set up our Node server. Navigate to the command line and execute <code>npm init</code>. This command creates a new Node project structure for you.</p>
<p>Next, install the Express package – this will serve as the backend framework. You can do this by running the <code>npm i express</code> command.</p>
<h2 id="heading-how-to-integrate-relevant-packages">How to Integrate Relevant Packages</h2>
<p>For the purpose of this tutorial, we’ll install the Sequelize Node package manager in our Node application in order to set up the ORM communication to the database.</p>
<p>To set this up, execute <code>npm i sequelize</code>.</p>
<p>We’ll use a locally hosted MySQL database. To do this, we’ll install an npm package database driver. In this case, we will be installing <code>mysql2</code>. Here is a link to the <a target="_blank" href="https://www.npmjs.com/package/sequelize"><code>package</code></a></p>
<p>Run <code>npm i mysql2</code> to install it.</p>
<p>Let’s move on to configuring the connection to the database and building our demo project.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>In this section we’ll build a simple backend server that performs Create-Read-Update-Delete operations, with the Sequelize library serving as the connection pipeline.</p>
<p>In order to begin the project, we’ll have to set up the database connection for our application. We’ll create a database connection file and set up our database credentials. You can name the file <strong>SequelizeConfig</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {

    <span class="hljs-attr">HOST</span>: <span class="hljs-string">"localhost"</span>,

    <span class="hljs-attr">USER</span>: <span class="hljs-string">"root"</span>,

    <span class="hljs-attr">PASSWORD</span>: <span class="hljs-string">""</span>,

    <span class="hljs-attr">DB</span>: <span class="hljs-string">"sequel"</span>,

    <span class="hljs-attr">dialect</span>: <span class="hljs-string">"mysql"</span>

}
</code></pre>
<p>In the code above, the database credentials were specified, along with the host address. In our case, the database is locally hosted, so localhost is the default host.</p>
<p>The database login details were also provided. The user here is the root, while the password was set to an empty string. This should be tweaked to ensure database security. I also created a defunct database named “sequel”.</p>
<p>The dialect refers to the type of database the user intends to use. In our case, the dialect is MySQL. Note that this can also be replicated on a cloud hosted database with the credentials obtained. With that, let's integrate the connection file with the application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> SequelConfig = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../config/sequelize'</span>);

<span class="hljs-keyword">const</span> Sequelize = <span class="hljs-built_in">require</span>(<span class="hljs-string">'sequelize'</span>);

<span class="hljs-keyword">const</span> sequelize = <span class="hljs-keyword">new</span> Sequelize(SequelCOnfig.DB, SequelCOnfig.USER, SequelCOnfig.PASSWORD, {

    <span class="hljs-attr">host</span>: SequelCOnfig.HOST,

    <span class="hljs-attr">dialect</span>: SequelCOnfig.dialect

});
</code></pre>
<p>In order to facilitate a connection to the database, the variables in the config file were imported and initialized in the Sequelize setup file.</p>
<pre><code class="lang-javascript">

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

db.Sequelize = Sequelize;

db.sequelize = sequelize;

db.user = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../model/user.model'</span>)(sequelize, Sequelize);

db.token = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../model/token.model'</span>)(sequelize, Sequelize)

<span class="hljs-built_in">module</span>.exports= db;
</code></pre>
<p>This file above imports the <code>config</code> file created previously and initializes the Sequelize library. The code then fetches the database details inputted in the config file and, when executed, creates the database.</p>
<p>Furthermore, the various database models which will be discussed subsequently are then integrated with the defunct database and generates a SQL database table .</p>
<p>To get this up and running, the database file created is invoked using the <code>sequelize.sync()</code> method. Any error encountered is logged and the database connection gets terminated.</p>
<pre><code class="lang-javascript">db.sequelize.sync().then(<span class="hljs-function">() =&gt;</span> {

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'user created '</span>);

}).catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {

  <span class="hljs-built_in">console</span>.error(err)

})
</code></pre>
<p>We’ll go on to discuss the database models.</p>
<h3 id="heading-models">Models</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Sequelize = <span class="hljs-built_in">require</span>(<span class="hljs-string">"sequelize"</span>);

<span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">sequelize</span>) =&gt;</span> {

sequelize.define(

<span class="hljs-string">"user"</span>, {

<span class="hljs-attr">firstName</span>: {

<span class="hljs-attr">type</span> : Sequelize.DataTypes.STRING,

<span class="hljs-attr">allowNull</span> : <span class="hljs-literal">false</span>

},

<span class="hljs-attr">lastName</span>: {

<span class="hljs-attr">type</span> : Sequelize.DataTypes.STRING,

<span class="hljs-attr">allowNull</span> : <span class="hljs-literal">false</span>

},

<span class="hljs-attr">email</span> : {

<span class="hljs-attr">type</span> : Sequelize.DataTypes.STRING,

<span class="hljs-attr">allowNull</span> : <span class="hljs-literal">false</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>

},

<span class="hljs-attr">password</span>: {

<span class="hljs-attr">type</span> : Sequelize.DataTypes.STRING,

<span class="hljs-attr">allowNull</span> : <span class="hljs-literal">false</span>

},

<span class="hljs-attr">role</span>:  {

<span class="hljs-attr">type</span> : Sequelize.DataTypes.STRING,

<span class="hljs-attr">allowNull</span> : <span class="hljs-literal">false</span>

}

}

)

}
</code></pre>
<p>In the code above, the user model was initialized in Sequelize ORM and the field details were specified: <code>email</code>, <code>role</code>, <code>lastName</code>, and <code>password</code>. The type of data to be received was also specified.</p>
<p>It also provides an option to ensure the uniqueness of the user details, and the option to prevent the user from leaving some fields empty via the use of <code>allowNull = false</code>.</p>
<p>On execution of the application, the Sequelize ORM creates an SQL equivalent of the model as a data table.</p>
<p>Next, we’ll work on the CRUD functions in Node.js.</p>
<h3 id="heading-create-operation">Create Operation</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> createUser = <span class="hljs-keyword">async</span> (userInfo) =&gt; {

<span class="hljs-keyword">try</span> {

<span class="hljs-comment">// Check if the email already exists in the database</span>

<span class="hljs-keyword">const</span> ifEmailExists = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">where</span>: { <span class="hljs-attr">email</span>: userInfo.email } });

<span class="hljs-keyword">if</span> (ifEmailExists) {

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApiError(<span class="hljs-string">'Email has already been registered'</span>);

}

<span class="hljs-comment">// Create the new user</span>

<span class="hljs-keyword">const</span> newUser = <span class="hljs-keyword">await</span> User.create(userInfo);

<span class="hljs-keyword">return</span> newUser; <span class="hljs-comment">// Return the created user object</span>

} <span class="hljs-keyword">catch</span> (error) {

<span class="hljs-comment">// Handle errors such as validation or uniqueness constraint</span>

<span class="hljs-keyword">throw</span> error;

}

};
</code></pre>
<p>The function above highlights the controller function for creating user entries in the Express server.</p>
<p>The function is asynchronous, which allows for execution of some commands before eventual execution. The code ensures that the user email doesn’t exist in the database before cresting a new user.</p>
<p>In addition, we also ensured that each email field is unique. If the user details are entered into the database successfully, a “successful” response is sent back to the server. Additionally, any error encountered leads to termination of the function and the error gets sent back to the server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728593905405/ae2b4fb6-0dfd-4e68-890b-a5d1afc88d71.png" alt="A POST request to create a new user endpoint" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-read-operation">Read Operation</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> FetchUser = <span class="hljs-keyword">async</span> (userId) =&gt; {

<span class="hljs-keyword">let</span> userDets;

<span class="hljs-keyword">if</span> (userId) {

<span class="hljs-comment">// Fetch a single user by ID if userId is provided</span>

userDets = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">where</span>: { <span class="hljs-attr">id</span>: userId } });

<span class="hljs-comment">// Check if the user exists</span>

<span class="hljs-keyword">if</span> (!userDets) {

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApiError(httpStatus.NOT_FOUND, <span class="hljs-string">'User not found'</span>);

}

} <span class="hljs-keyword">else</span> {

<span class="hljs-comment">// Fetch all users if no userId is provided</span>

userDets = <span class="hljs-keyword">await</span> User.findAll();

<span class="hljs-comment">// Check if any users were found</span>

<span class="hljs-keyword">if</span> (userDets.length === <span class="hljs-number">0</span>) {

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApiError(httpStatus.NOT_FOUND, <span class="hljs-string">'No users found'</span>);

}

}
</code></pre>
<p>The read operation fetches the desired query and sends it back to the user without modification. The user ID, which should be unique, is used to search for a specific user. In this scenario, we want access to all the users created in the database.</p>
<p>In case the requested query is not found, an appropriate error code is generated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728593791809/3e4dae9d-98ad-4966-b17a-b9649c41921d.png" alt="A GET request  to fetch all the users in the database endpoint" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-update-operation">Update Operation</h3>
<pre><code class="lang-javascript">

<span class="hljs-keyword">const</span> updateUser = <span class="hljs-keyword">async</span> (userId, userDetails) =&gt; {

<span class="hljs-comment">// First, find the user by their ID</span>

<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">where</span>: { <span class="hljs-attr">id</span>: userId } });

<span class="hljs-keyword">if</span> (!user) {

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApiError(httpStatus.BAD_REQUEST, <span class="hljs-string">"User doesn't exist"</span>);

}

<span class="hljs-comment">// Update the user with the new details</span>

<span class="hljs-keyword">await</span> User.update(userDetails, { <span class="hljs-attr">where</span>: { <span class="hljs-attr">id</span>: userId } });

<span class="hljs-comment">// Fetch the updated user to return it</span>

<span class="hljs-keyword">const</span> updatedUser = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">where</span>: { <span class="hljs-attr">id</span>: userId } });

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Updated user:'</span>, updatedUser); <span class="hljs-comment">// Log the updated user</span>

<span class="hljs-keyword">return</span> updatedUser; <span class="hljs-comment">// Return the updated user object</span>

};
</code></pre>
<p>The update operation aims to modify the data entered in previous operations. That is, to update some data fields.</p>
<p>In the case of Sequelize, the <code>update</code> method is invoked. To succeed with this, the particular user to be edited must be identified. The code above then generates the updated data field and sends it as the output of a successful request.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728593828831/33a2bf88-7f4c-4847-b139-e4d97dcd805b.png" alt="A PUT request to edit and update user details endpoint" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-delete-operation">Delete Operation</h3>
<pre><code class="lang-javascript">

<span class="hljs-keyword">const</span> deleteUser = <span class="hljs-keyword">async</span> (userId) =&gt; {

<span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">where</span>: { <span class="hljs-attr">id</span>: userId } });

<span class="hljs-keyword">if</span> (!user) {

<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApiError(httpStatus.BAD_REQUEST, <span class="hljs-string">"User doesn't exist"</span>);

}

<span class="hljs-comment">// Delete the user</span>

<span class="hljs-keyword">await</span> user.destroy();

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Deleted user:'</span>, user); <span class="hljs-comment">// Log the deleted user</span>

<span class="hljs-keyword">return</span> user; <span class="hljs-comment">// Return the deleted user object (useful for confirmation)</span>

};
</code></pre>
<p>The delete operation is invoked when data in the database table needs to be deleted. Sequelize makes provision for this via the use of the <code>destroy</code> method. This method deletes a specific user. When executed, a success response code is displayed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728593876348/ad01b671-5e93-4e34-afbb-dc2a961d576e.png" alt="A DELETE request to remove a particular user detail from the database" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-additional-information">Additional Information</h2>
<p>So far, we have integrated an ORM library to serve as a connection between our backend application and our relational database. We also explored advanced concepts such as database migrations and CRUD operations. To learn more about this, you can explore the documentation and utilize it in building more complex projects, as hands-on learning is much encouraged.</p>
<p>Feel free to reach out to me on my <a target="_blank" href="http://dev.to/oluwatobi2001">blog</a> and check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement API Rate Limiting in Strapi CMS ]]>
                </title>
                <description>
                    <![CDATA[ Implementing rate limiting in web applications is a necessary web development best practice. In an article published earlier, I delved deep into the benefits and real life use cases of API rate limiting. Some of the benefits include its use by develo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/implement-api-rate-limiting-in-strapi/</link>
                <guid isPermaLink="false">66e05529fcb93f325519038c</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Tue, 10 Sep 2024 14:18:17 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725233479497/7c12e6e4-a6d7-433a-b23b-f25c33037ffa.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Implementing rate limiting in web applications is a necessary web development best practice. In an <a target="_blank" href="https://www.freecodecamp.org/news/what-is-rate-limiting-web-apis/">article</a> published earlier, I delved deep into the benefits and real life use cases of API rate limiting.</p>
<p>Some of the benefits include its use by developers to restrict malicious access to websites, prevent DDoS attacks, conserve website resources, and ensure optimal web server performance.</p>
<p>This article covers the practical aspects of implementing rate limits in a Strapi application using several packages and techniques.</p>
<p>Let's get started.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-demo-project">Demo Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-koa2-rate-limit">Koa Rate Limiter</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-custom-strapi-api-rate-limiter">Custom Strapi Api Rate Limiter</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-express-rate-limiter-implementation">Express-rate-limiter Implementation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-demo-project">Demo Project</h2>
<p>We'll be building an e-commerce site using <a target="_blank" href="https://strapi.io/">Strapi</a> as our backend framework. We'll then set up a rate limiter in our Strapi application to help guarantee our backend security. Postman will serve as our tool for testing the API endpoints. Let's go on to create a default Strapi application.</p>
<p>To create a strapi application, enter <code>npx create-strapi-app@latest {project name}</code> on the command line and follow the commands provided. To make the installation more straightforward, stick with the <em>quick start</em> installation method and your app should be ready.</p>
<p>This installation modality automatically sets up an easy-to-use SQLite database. However, you could choose to use any other SQL database supported by Strapi.</p>
<p>Alternatively, you can download the starter repo for the project from <a target="_blank" href="https://github.com/oluwatobi2001/Strapi-default">here</a> and install the necessary dependencies via <code>npm install</code>. Thereafter, you can execute the Strapi application by navigating to the Strapi application code folder on the command line and run <code>npm run develop</code>.</p>
<p><img src="https://hackmd.io/_uploads/BkRn2PqrR.png" alt="Strapi Setup" width="600" height="400" loading="lazy"></p>
<p>On successful execution, you will be provided with the link to the localhost address to customize the application.</p>
<p><img src="https://hackmd.io/_uploads/SkkSavcS0.png" alt="Strapi launch" width="600" height="400" loading="lazy"></p>
<p>Navigating to the link will require you to create an admin login mail and password. Successful completion of this step will give you access to the backend dashboard.</p>
<p><img src="https://hackmd.io/_uploads/S1Vqxd5B0.png" alt="strapi login UI" width="600" height="400" loading="lazy"></p>
<p>You can utilize the Strapi dashboard UI to create APIs, or you can generate an API using <code>npm generate</code>. The APIs created will be used in completing the setup for the rate limiting functionality. We will be creating a product store for our e-commerce site. To easily set up products, kindly navigate to the Content-Type builder tab on the sidebar.  </p>
<p><img src="https://hackmd.io/_uploads/r1RzbO5BC.png" alt="strapi dashboard" width="600" height="400" loading="lazy"></p>
<p>The content-Type builder manager allows you to create various collections which will come in handy when setting up your APIs. In this case, the product and category collections will be created to enable you set up your product catalogues.</p>
<p><img src="https://hackmd.io/_uploads/B16rbu5rA.png" alt="Creating a category endpoint" width="600" height="400" loading="lazy"></p>
<p><img src="https://hackmd.io/_uploads/SJhdb_qSR.png" alt="Creating a product entry" width="600" height="400" loading="lazy"></p>
<p>After completing the creation of the collection types, you can easily add your products seamlessly into the backend database. In my case, I created phone brand products for sale.</p>
<p><img src="https://hackmd.io/_uploads/HyR9JT6fR.jpg" alt="Product creation demo" width="600" height="400" loading="lazy"></p>
<p>Also noteworthy is that the collections we created in the Strapi dashboard automatically creates an API folder for us within our codebase. We will then be working on the project codebase subsequently.</p>
<p>The next step in this tutorial is to set up an efficient rate limiter for our Strapi APIs created in the repo using the tools discussed above.</p>
<h2 id="heading-koa2-rate-limit">koa2-rate-limit</h2>
<p>In this section, we will be using the koa2-rate-limit package to build our project rate limiter. To install the package, navigate to your project folder on the command line and execute <code>npm i koa2-rate-limit</code>. On successful installation, navigate to the middleware subfolder within the API folder and create a code file. For ease of integration, name it as <strong>rateLimit.js</strong>.</p>
<p>After that, within the rate limit file, import and initialize the koa2-rate limit package.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> RateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">"koa2-ratelimit"</span>).RateLimit;
</code></pre>
<p>Afterwards, we can configure the koa rate limiter to a specified time interval frame and the total number of requests.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">config, { strapi }</span>) =&gt;</span> {
  <span class="hljs-comment">// Configuring the rate limiter middleware</span>
  <span class="hljs-keyword">const</span> limiter = RateLimit.middleware({
    <span class="hljs-attr">interval</span>: { <span class="hljs-attr">min</span>: <span class="hljs-number">1</span> }, <span class="hljs-comment">// Time window in minutes</span>
    <span class="hljs-attr">max</span>: <span class="hljs-number">3</span>, <span class="hljs-comment">// Maximum number of requests per interval</span>
 });
</code></pre>
<p>In the code above, the rate limiter middleware was invoked and the time interval in which the rate limit gets applied was set to 1 minute. The maximum number of requests (max) was set to 3 for this tutorial. You can tweak this to suit your preference.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (ctx, next) =&gt; {


    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Apply the rate limiter to the current request</span>
      <span class="hljs-keyword">await</span> limiter(ctx, next);
 } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-keyword">if</span> (err.status === <span class="hljs-number">429</span>) {
        <span class="hljs-comment">// Handle rate limit exceeded error</span>
        strapi.log.warn(<span class="hljs-string">'Rate limit exceeded.'</span>);
        ctx.status = <span class="hljs-number">429</span>;
        ctx.body = {
          <span class="hljs-attr">statusCode</span>: <span class="hljs-number">429</span>,
          <span class="hljs-attr">error</span>: <span class="hljs-string">'Too Many Requests'</span>,
          <span class="hljs-attr">message</span>: <span class="hljs-string">'You have exceeded the maximum number of requests. Please try again later.'</span>,
 };
 } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// Re-throw other errors to be handled by Strapi's error-handling middleware</span>
        <span class="hljs-keyword">throw</span> err;
 }
 }
</code></pre>
<p>The code above defines a middleware which gets executed whenever a function is made on any API. If the requests exceed the given maximum, an error code is outputted. Below is the full code.</p>
<pre><code class="lang-javascript"><span class="hljs-meta">
'use strict'</span>;

<span class="hljs-comment">/**
 * `RateLimit` middleware
 */</span>
<span class="hljs-keyword">const</span> RateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">"koa2-ratelimit"</span>).RateLimit;

<span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">config, { strapi }</span>) =&gt;</span> {
  <span class="hljs-comment">// Configuring the rate limiter middleware</span>
  <span class="hljs-keyword">const</span> limiter = RateLimit.middleware({
    <span class="hljs-attr">interval</span>: { <span class="hljs-attr">min</span>: <span class="hljs-number">1</span> }, <span class="hljs-comment">// Time window in minutes</span>
    <span class="hljs-attr">max</span>: <span class="hljs-number">3</span>, <span class="hljs-comment">// Maximum number of requests per interval</span>
 });

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (ctx, next) =&gt; {

    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Apply the rate limiter to the current request</span>
      <span class="hljs-keyword">await</span> limiter(ctx, next);
 } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-keyword">if</span> (err.status === <span class="hljs-number">429</span>) {
        <span class="hljs-comment">// Handle rate limit exceeded error</span>
        strapi.log.warn(<span class="hljs-string">'Rate limit exceeded.'</span>);
        ctx.status = <span class="hljs-number">429</span>;
        ctx.body = {
          <span class="hljs-attr">statusCode</span>: <span class="hljs-number">429</span>,
          <span class="hljs-attr">error</span>: <span class="hljs-string">'Too Many Requests'</span>,
          <span class="hljs-attr">message</span>: <span class="hljs-string">'You have exceeded the maximum number of requests. Please try again later.'</span>,
 };
 } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// Re-throw other errors to be handled by Strapi's error-handling middleware</span>
        <span class="hljs-keyword">throw</span> err;
 }
 }

 };
};
</code></pre>
<p>To ensure its seamless integration to all APIs within the Strapi project, the admin middlewares must also be configured.</p>
<pre><code class="lang-javascript">cconst rateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middlewares/rateLimit'</span>);

<span class="hljs-built_in">module</span>.exports = [
 <span class="hljs-string">'strapi::logger'</span>,
 <span class="hljs-string">'strapi::errors'</span>,
 <span class="hljs-string">'strapi::security'</span>,
 <span class="hljs-string">'strapi::cors'</span>,
 <span class="hljs-string">'strapi::poweredBy'</span>,
 <span class="hljs-string">'strapi::query'</span>,
 <span class="hljs-string">'strapi::body'</span>,
 <span class="hljs-string">'strapi::session'</span>,
 <span class="hljs-string">'strapi::favicon'</span>,
 <span class="hljs-string">'strapi::public'</span>,

 {
   <span class="hljs-attr">name</span>: <span class="hljs-string">'global::rateLimit'</span>,
   <span class="hljs-attr">config</span>: {},
 },
];
</code></pre>
<p>With this, we have successfully configured the rate limiter powered by koa2-ratelimiter. Here are pictures of its execution.</p>
<p><img src="https://hackmd.io/_uploads/Bybbd-hj0.png" alt="Postman testing the categories endpoint" width="600" height="400" loading="lazy"></p>
<p><img src="https://hackmd.io/_uploads/r1Zb_-3jC.png" alt="rate limiting error response output" width="600" height="400" loading="lazy"></p>
<h2 id="heading-custom-strapi-api-rate-limiter">Custom Strapi Api Rate Limiter</h2>
<p>Within the <strong>rateLimit</strong> file in the <strong>API/middlewares</strong> folder, create a custom rate limiter by initializing a memory store.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> requestCounts = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
</code></pre>
<p>Thereafter, define your rate limit function and then configure the rate limiter.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">config, { strapi }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> rateLimitConfig = strapi.config.get(<span class="hljs-string">'admin.rateLimit'</span>, {
    <span class="hljs-attr">interval</span>: <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>,  
    <span class="hljs-attr">max</span>: <span class="hljs-number">3</span>,  
 });
</code></pre>
<p>The time interval above is 1 minute while the maximum number of requests that can be made within the specified time interval is 3. You can tweak it to suit your preference.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (ctx, next) =&gt; {

    <span class="hljs-keyword">const</span> ip = ctx.ip; 
    <span class="hljs-keyword">const</span> currentTime = <span class="hljs-built_in">Date</span>.now();

    <span class="hljs-keyword">if</span> (!requestCounts.has(ip)) {

      requestCounts.set(ip, { <span class="hljs-attr">count</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">startTime</span>: currentTime });
 } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">const</span> requestInfo = requestCounts.get(ip);


      <span class="hljs-keyword">if</span> (currentTime - requestInfo.startTime &gt; rateLimitConfig.interval) {
        requestInfo.count = <span class="hljs-number">1</span>;
        requestInfo.startTime = currentTime;
 } <span class="hljs-keyword">else</span> {

 }


      <span class="hljs-keyword">if</span> (requestInfo.count &gt; rateLimitConfig.max) {
        strapi.log.warn(<span class="hljs-string">`Rate limit exceeded for IP: <span class="hljs-subst">${ip}</span>`</span>);

        ctx.status = <span class="hljs-number">429</span>;
        ctx.body = {
          <span class="hljs-attr">statusCode</span>: <span class="hljs-number">429</span>,
          <span class="hljs-attr">error</span>: <span class="hljs-string">'Too Many Requests'</span>,
          <span class="hljs-attr">message</span>: <span class="hljs-string">'You have exceeded the maximum number of requests. Please try again later.'</span>,
 };
        <span class="hljs-keyword">return</span>;
 }
 }

    <span class="hljs-keyword">await</span> next();
 };
};
</code></pre>
<p>Afterwards, a middleware is defined which obtains the user IP address and then stores it in the memory store. The time interval is also set from the current time the request is made and the request count gets updated with every new request made.</p>
<p>If the requests made exceed the maximum expected requests within the time interval of 1 minute in our case, an error is thrown. Here is the full code below.</p>
<pre><code class="lang-javascript"><span class="hljs-meta">'use strict'</span>;
<span class="hljs-keyword">const</span> requestCounts = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-built_in">module</span>.exports = <span class="hljs-function">(<span class="hljs-params">config, { strapi }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> rateLimitConfig = strapi.config.get(<span class="hljs-string">'admin.rateLimit'</span>, {
    <span class="hljs-attr">interval</span>: <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>,  
    <span class="hljs-attr">max</span>: <span class="hljs-number">3</span>,  
 });

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">async</span> (ctx, next) =&gt; {

    <span class="hljs-keyword">const</span> ip = ctx.ip; 
    <span class="hljs-keyword">const</span> currentTime = <span class="hljs-built_in">Date</span>.now();

    <span class="hljs-keyword">if</span> (!requestCounts.has(ip)) {

      requestCounts.set(ip, { <span class="hljs-attr">count</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">startTime</span>: currentTime });
 } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">const</span> requestInfo = requestCounts.get(ip);


      <span class="hljs-keyword">if</span> (currentTime - requestInfo.startTime &gt; rateLimitConfig.interval) {
        requestInfo.count = <span class="hljs-number">1</span>;
        requestInfo.startTime = currentTime;
 } <span class="hljs-keyword">else</span> {

        requestInfo.count += <span class="hljs-number">1</span>;
 }


      <span class="hljs-keyword">if</span> (requestInfo.count &gt; rateLimitConfig.max) {


        ctx.status = <span class="hljs-number">429</span>;
        ctx.body = {
          <span class="hljs-attr">statusCode</span>: <span class="hljs-number">429</span>,
          <span class="hljs-attr">error</span>: <span class="hljs-string">'Too Many Requests'</span>,
          <span class="hljs-attr">message</span>: <span class="hljs-string">'You have exceeded the maximum number of requests. Please try again later.'</span>,
 };
        <span class="hljs-keyword">return</span>;
 }
 }

    <span class="hljs-keyword">await</span> next();
 };
};
</code></pre>
<p>Here is a demo of the project.</p>
<p><img src="https://hackmd.io/_uploads/BkIyHZ2j0.png" alt="fetching the categories on Postman" width="600" height="400" loading="lazy"></p>
<p><img src="https://hackmd.io/_uploads/HyxgHW2i0.png" alt="rate limiting error on Postman" width="600" height="400" loading="lazy"></p>
<h3 id="heading-express-rate-limiter-implementation">Express-rate-limiter Implementation</h3>
<p>Express rate limiter is also another important package that can be used to implement rate limiting in our project. Right now, this package will be used to implement a route-specific API rate limiting.</p>
<p>The next step in this tutorial is setting up an efficient rate limiter for our Strapi APIs created in the repo.</p>
<p>To set up rate limiters on our Strapi applications, we'll be working mainly on the <strong>routes</strong> file. This can be navigated to by accessing the <strong>src</strong> folder within the project root directory. Within the <strong>src</strong> folder, navigate to the <strong>API</strong> folder which contains all the API files for the collections created in the Strapi dashboard.</p>
<p><img src="https://hackmd.io/_uploads/S1ERbxndR.png" alt="the product route directory" width="600" height="400" loading="lazy"></p>
<p>The rate limiter will be enforced in the routes section of each API. For this tutorial, I will be using the products API as a demo API in this article.</p>
<pre><code class="lang-javascript"><span class="hljs-meta">'use strict'</span>;


<span class="hljs-comment">/**
 * product router
 */</span>

<span class="hljs-keyword">const</span> { createCoreRouter } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@strapi/strapi'</span>).factories;

<span class="hljs-built_in">module</span>.exports = createCoreRouter(<span class="hljs-string">'api::product.product'</span>);
</code></pre>
<p>This is the initial code setup in the <strong>routes.js</strong> file in our product API folder. The rate limiting tool of choice for this tutorial is express-rate-limit as it offers much simplicity and user-friendliness coupled with its efficiency. Here is a link to its <a target="_blank" href="https://www.npmjs.com/package/express-rate-limit">documentation</a>. To get this installed, navigate to the command line of the project directory and run</p>
<pre><code class="lang-bash">npm install express-rate-limit
</code></pre>
<p>On completion of its installation, we will be initializing it in the <strong>products</strong> file already created within the <strong>routes</strong> folder as follows.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { rateLimit } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express-rate-limit"</span>);
</code></pre>
<p>Go on and configure the rate limiter to your desired specifications.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> rateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express-rate-limit'</span>);

<span class="hljs-keyword">const</span> limiter = rateLimit({
  <span class="hljs-attr">windowMs</span>: <span class="hljs-number">3</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>, <span class="hljs-comment">// 3 minutes</span>
  <span class="hljs-attr">max</span>: <span class="hljs-number">2</span>, <span class="hljs-comment">// limit each IP to 2 requests per windowMs</span>
  <span class="hljs-attr">handler</span>: <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">const</span> ctx = strapi.requestContext.get();
    ctx.status = <span class="hljs-number">429</span>;
    ctx.body = {
      <span class="hljs-attr">message</span>: <span class="hljs-string">"Too many requests"</span>,
      <span class="hljs-attr">policy</span>: <span class="hljs-string">"rate limit"</span>
    };
    <span class="hljs-comment">// Ensure the response is ended after setting the response body and status</span>
    ctx.res.end();
  }
});

<span class="hljs-built_in">module</span>.exports = limiter;
</code></pre>
<p>The code above serves to configure the rate limiting parameters we intend to use for the file.</p>
<p><code>windowMs</code> represents the time interval in milliseconds for the number of requests. In our case, we specified a time of 3 minutes. Also, we specified the maximum number of requests that can be made within that same time frame. In our case, we used 2 for demo purposes.</p>
<p>However, the <code>limit</code> parameter also serves as an alternative to <code>max</code> parameter. Also included is the handler function that gets executed whenever the requests exceed the set number. It returns an <strong>Error 429</strong> with an error body containing “Too many requests”.</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">const</span> { createCoreRouter } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@strapi/strapi'</span>).factories;

<span class="hljs-built_in">module</span>.exports = createCoreRouter(<span class="hljs-string">'api::product.product'</span>, {
  <span class="hljs-attr">config</span>: {
    <span class="hljs-attr">find</span>: {
      <span class="hljs-attr">middlewares</span>: [
        <span class="hljs-keyword">async</span> (ctx, next) =&gt; {
          <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
            limiter(ctx.req, ctx.res, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
              <span class="hljs-keyword">if</span> (error) {
                ctx.status = <span class="hljs-number">429</span>;
                ctx.body = { <span class="hljs-attr">error</span>: error.message };
                reject(error);
              } <span class="hljs-keyword">else</span> {
                resolve();
              }
            });
          });
          <span class="hljs-keyword">await</span> next();
        }
      ]
    }
  }
});
</code></pre>
<p>The above code illustrates the use of the Strapi API middleware which serves to ensure that the rate limit is fulfilled before the onward execution of the API requests. It also ensures that the request is terminated when the rate limit gets exceeded. Here is the final code for the project.</p>
<pre><code class="lang-javascript"><span class="hljs-meta">'use strict'</span>;

<span class="hljs-comment">/**
 * product router
 */</span>

<span class="hljs-keyword">const</span> { createCoreRouter } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@strapi/strapi'</span>).factories;
<span class="hljs-keyword">const</span> rateLimit = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express-rate-limit'</span>);

<span class="hljs-keyword">const</span> limiter = rateLimit({
  <span class="hljs-attr">windowMs</span>: <span class="hljs-number">3</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>, <span class="hljs-comment">// 3 minutes</span>
  <span class="hljs-attr">max</span>: <span class="hljs-number">2</span>, <span class="hljs-comment">// limit each IP to 2 requests per windowMs</span>
  <span class="hljs-attr">handler</span>: <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">const</span> ctx = strapi.requestContext.get();
    ctx.status = <span class="hljs-number">429</span>;
    ctx.body = {
      <span class="hljs-attr">message</span>: <span class="hljs-string">'Too many requests'</span>,
      <span class="hljs-attr">policy</span>: <span class="hljs-string">'rate limit'</span>
    };
    <span class="hljs-comment">// Ensure the response is ended after setting the response body and status</span>
    ctx.res.end();
  }
});

<span class="hljs-built_in">module</span>.exports = createCoreRouter(<span class="hljs-string">'api::product.product'</span>, {
  <span class="hljs-attr">config</span>: {
    <span class="hljs-attr">find</span>: {
      <span class="hljs-attr">middlewares</span>: [
        <span class="hljs-keyword">async</span> (ctx, next) =&gt; {
          <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
            limiter(ctx.req, ctx.res, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {

              <span class="hljs-keyword">if</span> (error) {
                ctx.status = <span class="hljs-number">429</span>;
                ctx.body = { <span class="hljs-attr">error</span>: error.message };
                reject(error);
              } <span class="hljs-keyword">else</span> {
                resolve();
              }
            });
          });
          <span class="hljs-keyword">if</span> (ctx.status !== <span class="hljs-number">429</span>) {
            <span class="hljs-keyword">await</span> next();
          }
        }
      ]
    }
  }
});
</code></pre>
<p>Here is an image showing the rate limiting functionality.</p>
<p><img src="https://hackmd.io/_uploads/S116Wu9BR.png" alt="product endpoint testing in Postman" width="600" height="400" loading="lazy"></p>
<p><img src="https://hackmd.io/_uploads/S1zMGO5B0.png" alt="ratelimit successfully executed" width="600" height="400" loading="lazy"></p>
<p>You can also download the final code for the project <a target="_blank" href="https://github.com/oluwatobi2001/Strapi-project">here</a>. Having completed this, you can then go ahead to test the rate limiting functionality of your API. The Strapi application can be run by executing <code>npm run develop</code> in the command line.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learned essentially about rate limiting, its uses, tools and best practices.</p>
<p>You can also design multiple rate limiters within the code and implement them in any endpoint of your choice to test it out.</p>
<p>Feel free to drop any questions or comments. Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Rate Limiting? Exploring the Role of Rate Limiting in Protecting Web APIs from Attacks ]]>
                </title>
                <description>
                    <![CDATA[ Back-end servers are the powerhouse of modern-day applications; hence, a high level of expertise goes into building them. However, it's important to ensure that these back-end servers are well-secured from bad actors (hackers, phishers). These bad el... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-rate-limiting-web-apis/</link>
                <guid isPermaLink="false">66d884befdf6891c419f8901</guid>
                
                    <category>
                        <![CDATA[ #cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 04 Sep 2024 16:03:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725036062594/0efa7e12-c5d5-410f-ad9c-ec6a67a31f7c.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Back-end servers are the powerhouse of modern-day applications; hence, a high level of expertise goes into building them. However, it's important to ensure that these back-end servers are well-secured from bad actors (hackers, phishers).</p>
<p>These bad elements access the back-end servers through vulnerable points in the gateways to wreak havoc, stealing relevant info and negatively affecting application performance and efficiency via various forms of API attacks such as SQL and non-SQL-based injections, Distributed Denial-of-Service (DDoS) attacks, code malware, and other methods to exploit vulnerabilities.</p>
<p>In this article, I will be focusing on rate limiting, an important hack that helps protect the back-end API from being exploited by hackers via the use of DDoS, Brute-force attacks and other related malicious activities. But first of all, what does rate limiting mean?</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-rate-limiting">What is Rate Limitin</a><a class="post-section-overview" href="#heading-what-is-rate-limiting">g?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-importance-of-rate-limiting">Importance of Rate Limiting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-adoption-and-usage-of-rate-limiting-by-popular-sites">Adoption and Usage of Rate-Limiting by Popular Sites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-other-real-life-use-cases-of-api-rate-limiting">Other Real life Use-cases of API Rate Limiting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-does-rate-limiting-work">How Does Rate Limiting Work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-examples-of-rate-limiting-algorithms">Examples of Rate Limiting Algorithms</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-rate-limiting-best-practices">Rate Limiting Best Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-is-rate-limiting">What is Rate Limiting?</h2>
<p>Rate limiting is a mechanism put in place to regulate the frequency of requests made by a client to the back-end server. It prevents the repetition of a client request within a defined time frame.</p>
<p>Why do we have to implement rate limiting in the API development? We'll discuss that in the next section.</p>
<h2 id="heading-importance-of-rate-limiting">Importance of Rate Limiting</h2>
<p>Here are some of the reasons why rate limiting is used in back-end application development.</p>
<h3 id="heading-ddos-attacks">DDoS Attacks</h3>
<p>First of all, it serves as a preventive measure to mitigate against DDoS attacks. DDoS attacks are malicious attacks on servers which involves flooding the server endpoints with multiple requests, often millions, resulting in reduced server efficiency and disruption of server functions. In most cases, they occur with the use of automated bots.</p>
<p>These attacks can be volumetric, protocol-based or application layer-based. A key example of this form of attack occurred on the GitHub website in the year 2018.</p>
<h3 id="heading-web-scraping">Web Scraping</h3>
<p>Rate limiting also plays a role in protecting web applications and web servers from unauthorized web scrapers and web crawlers. These tools, also automated, usually emit requests continually to collect relevant website data which can be exposed to unauthorized. Having a good rate limiter in place helps to prevent all these.</p>
<h3 id="heading-brute-force-attack">Brute Force Attack</h3>
<p>This involves trying to gain access to a server's resources by trying all possible configurations to get access to the resource. This could be done manually but is mostly automated with the use of bots as it is resource-consuming. Rate limiting also proves effective in preventing these form of attacks by disabling the requests if they exceed the required number of requests within a specific time frame.</p>
<h3 id="heading-resource-optimization">Resource Optimization</h3>
<p>Server requests usually cost the API owners some expenses in terms of running and maintenance cost. Having a rate limiter in place helps to regulate the number of requests the server can handle, help conserve cost and maximize efficiency. Subsequently, we will highlight some algorithms which rate limiters are built on.</p>
<h2 id="heading-adoption-and-usage-of-rate-limiting-by-popular-sites">Adoption and Usage of Rate-Limiting by Popular Sites</h2>
<p>Rate limiting as a security measure has been adopted by a lot of tech products, ranging from large-scale to small-scale applications. For example, Twitter (X) has a rale limit feature implemented in the application programming interfaces they provide to developers.</p>
<p>These interfaces allow access to Twitter sign-up extension and other features made available by Twitter. To guarantee the efficient running of these interfaces, Twitter imposed a rate limit of 50 tweet post requests per user every 24 hours. More details about this can be found <a target="_blank" href="https://developer.twitter.com/en/docs/twitter-api/rate-limits">here</a>.</p>
<h2 id="heading-other-real-life-use-cases-of-api-rate-limiting">Other Real life Use-cases of API Rate Limiting</h2>
<p>The use of an application programming interface isn't limited to just what popular sites like Twitter use it for. Here are some other real-life applications of rate-limiting in today's world.</p>
<h3 id="heading-reducing-the-incidence-of-spamming">Reducing the Incidence of Spamming</h3>
<p><a target="_blank" href="https://www.emailtooltester.com/en/blog/spam-statistics/#:~:text=Survey%20Methodology-,Key%20statistics,spam%20messages%20in%20some%20form.">Research</a> reveals that over 160 billion spam emails are sent daily. Hence this has prompted the implementation of rate-limiting to curb the spread of unsolicited messages and spam content via messaging and emailing platforms over a specific time range. By so doing, it encourages responsible use of these platforms.</p>
<h3 id="heading-tackling-fraudulent-activities">Tackling Fraudulent Activities</h3>
<p>Rate limiting is currently implemented across web applications to help detect unusual web application activities by some users which may possess fraudulent intents. This measure serves to prevent and mitigate the ongoing fraudulent transactions being performed over the application server.</p>
<h3 id="heading-disabling-malicious-user-authentication">Disabling Malicious User Authentication</h3>
<p>Individuals with malicious intent may want to compromise the web servers by taking several measures such as brute force, DDoS and other techniques to take over other users' accounts.</p>
<p>However, several sites have efficient rate limit systems in places which limit the amount of login attempts an individual has to a site within a specific time range. This also contributes to web security measures.</p>
<h2 id="heading-how-does-rate-limiting-work">How Does Rate Limiting Work?</h2>
<p>Rate-limiting tools used in applications are implemented based on different algorithm structures. These algorithms guide the functionality of the rate-limiting tool whose end goal is to limit the number of requests a server receives per time to enhance its efficiency.</p>
<h2 id="heading-examples-of-rate-limiting-algorithms">Examples of Rate Limiting Algorithms</h2>
<p>Here are some of the most popular algorithms currently in use.</p>
<h3 id="heading-fixed-window-algorithm">Fixed Window Algorithm</h3>
<p>This algorithm is based on fixing a static definite time interval by the server for all clients, regulating the number of requests that can be made to the server, irrespective of the number of clients accessing the API.</p>
<p>For example, setting a request limit of five minutes prevents any client from accessing the endpoint until the expiration of the five minutes window. This model isn’t cost-effective.</p>
<h3 id="heading-sliding-window-algorithm">Sliding Window Algorithm</h3>
<p>This algorithm is similar in configuration to the fixed window algorithm but it provides a solution to the fixed window algorithm by individualizing client access to a given number of requests within a specific time interval by creating independent time intervals for each client.</p>
<p>For example, if Client A accesses the request by 10:00, the client is allowed to make 10 requests until the expiration of the time by 10:03, while Client B who accesses the request by 10:02 is allowed to make 10 requests until the expiration by 10:05.</p>
<h3 id="heading-leaking-bucket-algorithm">Leaking Bucket Algorithm</h3>
<p>This algorithm is based on the literal meaning of its name: the leaking bucket. It ensures that only a specific number of requests can be processed by the server at any given time. Any requests exceeding this number will be discarded and issued an "<strong>error 429</strong>". This is to ensure that the server is not overloaded and to guarantee maintenance of server efficiency and speed.</p>
<h3 id="heading-token-bucket-algorithm">Token Bucket Algorithm</h3>
<p>This model is similar to the leaking bucket as there is a hypothetical bucket which serves as the rate limiter. This bucket serves to manage tokens and new tokens are added periodically into the bucket.</p>
<p>When a request is made, a token gets discarded, and this continues until all the tokens in the bucket get depleted. At that point, any request made will be discarded with an "<strong>error 429</strong>". This also helps to prevent server congestion and ensure maximal efficiency.</p>
<h2 id="heading-rate-limiting-best-practices">Rate Limiting Best Practices</h2>
<p>Efficient web API development is mainly achievable by following the best API development practices. To maximize the use of a rate limiter as an API security measure, the following needs to be implemented.</p>
<ul>
<li><p><strong>Firstly, choose a compatible rate-limiting algorithm.</strong> Having a strong rate-limiting algorithm in place will be essential to achieve the desired result. Choosing the best rate-limiting algorithm in sync with your API endpoint will also be needed.</p>
</li>
<li><p><strong>Ensure that the limit sets are within the reasonable limit ranges</strong>. Having arbitrary rate limit parameters set could negatively affect user experience and that could defeat its purpose. Setting a reasonable time limit to maximize user experience and militate against attacks has proven to be much more effective.</p>
</li>
<li><p><strong>Ensure efficient error handling and provide necessary feedback to the client.</strong> The default rate limiting error code is error code 429. Appropriate handling of the errors that occur during the API usage especially due to the abuse of the API will be necessary to provide the necessary feedback to the user.</p>
</li>
<li><p><strong>Implement flexible rate-limiting mechanisms across several parameters.</strong> Setting a fixed time interval across all endpoints seems to be a bad practice as some API endpoints are much more data-sensitive than others. Hence, having a flexible rate limiter that sets parameters in order of relevance helps to maximize server efficiency and ensure security.</p>
</li>
<li><p><strong>Ensure the provision of appropriate application logging, monitoring and observability tools.</strong> Having in place API metrics, logging, monitoring and observability tools also helps to serve as an additional security hack for Web APIs as they help monitor server activity, and through the use of monitoring alerts, notify the server developer when suspicious requests are detected on the server.</p>
</li>
<li><p><strong>Ensure synchronicity of rate limiting and other API security measures.</strong> Proper synchronicity of rate limiters with other API security hacks should be harnessed to potentiate the API security measures. Adequate knowledge of the security measures and expertise is needed in order not to counteract the existing security measures.</p>
</li>
<li><p><strong>Ensure proper API documentation.</strong> Adequate API documentation is also needed to ensure users, other developers and clients alike are aware of the rate-limiting practice in place to ensure compliance with the rate-limiting rules.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, we have highlighted rate limiting as an important API security hack and some of it's real life use cases.</p>
<p>Feel free to check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Message Queues in Your Backend Applications ]]>
                </title>
                <description>
                    <![CDATA[ The goal of every web developer is to create a product that appeals to a wide range of users. However, this comes with its problems, chief among them being scalability issues to meet overwhelming user demands. If not addressed, this can result in a d... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-message-queues-in-your-backend-applications/</link>
                <guid isPermaLink="false">66bc7f37f9d5ce174cf0c403</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ queue ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 14 Aug 2024 09:56:07 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723280791863/cdc4faaa-2f95-4219-8753-881dfcafbf45.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The goal of every web developer is to create a product that appeals to a wide range of users. However, this comes with its problems, chief among them being scalability issues to meet overwhelming user demands.</p>
<p>If not addressed, this can result in a disarray of communication among services, defeating the measures placed to ensure orderly database transactions. But thank goodness, we have message brokers to the rescue.</p>
<p>In this article, we'll highlight the importance of message queuing as a best practice for backend development, relevant use cases and popular message queuing tools, and how to implement message queuing in backend applications.</p>
<p>Here are some of the prerequisites to be able to follow along in this article:</p>
<ul>
<li><p>Knowledge of Node.js</p>
</li>
<li><p>Knowledge of microservices architecture</p>
</li>
</ul>
<h2 id="heading-what-is-message-queuing">What is Message Queuing?</h2>
<p>In distributed systems, several requests and queues are sent at a time. The concept of a message queue enables the storage of messages in an orderly manner, allowing for the recipients of these messages and requests to process them accordingly.</p>
<p>It operates asynchronously, allowing the independent functioning of different components of a distributed system. Having these in place ensures that the messages sent to the recipient eventually get attended to irrespective of a system downtime. The messages are securely stored until they get acknowledged.</p>
<h3 id="heading-relevant-use-cases-of-message-brokers">Relevant Use Cases of Message Brokers</h3>
<p>Here are some of the real-life use cases of message brokers.</p>
<ul>
<li><p>They are actively used in modern fintech applications to ensure seamless and orderly execution and processing of financial transactions made on the application. This helps to prevent server overload and transaction errors.</p>
</li>
<li><p>Message queueing is also used in our day-to-day notification applications, ensuring early reception of sent notifications from other services. This allows the recipient to get access to those notifications notwithstanding the time they were sent or when the recipient gets access to the notification application.</p>
</li>
<li><p>It is also used in the financial markets for seamless and efficient execution of financial orders being made. Other uses of this feature are seen in media streaming and the healthcare industry.</p>
</li>
</ul>
<p>In the next paragraph, we'll discuss more about the tools that offer message queueing features.</p>
<h2 id="heading-examples-of-popular-message-queue-services">Examples of Popular Message Queue Services</h2>
<p>A wide range of applications and services offer message queueing features. Some of these services are embedded in commercial cloud infrastructure providers. Here is a list of some commonly used message queueing services:</p>
<ul>
<li><p>RabbitMQ</p>
</li>
<li><p>Apache Kafka</p>
</li>
<li><p>Redis</p>
</li>
<li><p>Amazon SQS</p>
</li>
<li><p>Google Cloud Pub/sub</p>
</li>
<li><p>NATS</p>
</li>
<li><p>Pulsar</p>
</li>
<li><p>IBM MQ</p>
</li>
</ul>
<p>We'll be utilizing a Rabbit MQ Cloud-as-a-service application to power our messages due to its popularity and ease of use. Here is a link to the <a target="_blank" href="https://www.cloudamqp.com/docs/index.html">documentation</a>. You can also check out other message queuing applications provided above.</p>
<p>Next, we'll develop a demo project that utilizes message queuing features.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>In this project, we'll use Rabbit MQ as a service cloud platform to build a simple message broker system that allows for seamless, ordered communication between two Node.js servers.</p>
<p>In this tutorial, we'll create a message publisher that will serve as the sender, and a message consumer that receives the messages.</p>
<p>To begin with, we'll have to create both Node.js servers that will be communicating with each other.</p>
<p>You can create two different files and initialize a Node project using <code>npm init</code>.</p>
<p>Thereafter, you can install relevant packages that will aid in the implementation of the features. We'll use the <code>amqplib</code> library, a Node library implementation for Rabbit MQ.</p>
<p>This package allows us to swiftly communicate with RabbitMQ via the Node.js application. It seamlessly achieves this due to its built-in functions for creating queues, publishing messages, and consuming messages. More details regarding its usage will be discussed later.</p>
<p>To install this in our project, kindly execute:</p>
<pre><code class="lang-javascript">npm i amqplib
</code></pre>
<p>The publish function will now be drafted. After that, we'll have to initialize <code>amqplib</code> in our project.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amp = <span class="hljs-built_in">require</span>(“amqplib”)
</code></pre>
<p>Also, we need to set up our RabbitMQ broker which will manage our messages.</p>
<p>There are several ways of creating RabbitMQ servers, the most popular being installing them on a home computer and then setting them up to interact with the backend servers. You can download the software <a target="_blank" href="https://www.rabbitmq.com/docs/download">here</a>. However, for ease of usage, we will be utilizing a cloud-based RabbitMQ broker as a service application to generate our server.</p>
<p>To get this done, kindly navigate to <a target="_blank" href="https://www.cloudamqp.com/">https://www.cloudamqp.com/</a> and create an account. For this tutorial, an instance was created and configured to the closest region to me. On successful creation of the instance, the details of the Rabbit MQ will be made available.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/cloudAmpq.PNG" alt="CloudAMQP home page" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/instance.PNG" alt="Creating  a free instance on CloudAMQP" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/amqpdets.PNG" alt="Details of the Free instance created" width="600" height="400" loading="lazy"></p>
<p>Moving on, we will be creating a message queue in which both parties can use as a connection pipeline. We will begin by creating a function to send messages.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">msg</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.sendToQueue(queue, Buffer.from(msg));
</code></pre>
<p>In the code above, a connection was ensured and maintained. Thereafter, a communication channel was also created. The assert queue function is then declared when executed, ensuring that the existing queue is maintained, and creates the queue if it doesn't exist.</p>
<p>The message attached to the function gets buffered and then sent to the queue created.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">receiveMessage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.consume(queue, <span class="hljs-function">(<span class="hljs-params">msg</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received message: <span class="hljs-subst">${msg.content.toString()}</span>`</span>);
      channel.ack(msg);
    });
</code></pre>
<p>The receiver function also gets executed to receive any message that gets into the queue by executing the consume method at the exact queue. In our case, the message is outputted as a log message.</p>
<p>The <code>ack</code> function is now executed to acknowledge the message received from the queue.</p>
<p>Here is the full project code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amqp = <span class="hljs-built_in">require</span>(<span class="hljs-string">"amqplib"</span>);
<span class="hljs-keyword">const</span> url = <span class="hljs-string">"amqp://localhost"</span>; <span class="hljs-comment">// Replace with your RabbitMQ server URL</span>
<span class="hljs-keyword">const</span> queue = <span class="hljs-string">"queue"</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">receiveMessage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.consume(queue, <span class="hljs-function">(<span class="hljs-params">msg</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (msg !== <span class="hljs-literal">null</span>) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Received message: <span class="hljs-subst">${msg.content.toString()}</span>`</span>);
        channel.ack(msg);
      }
    });
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to receive message:"</span>, err);
  }
}

receiveMessage();
</code></pre>
<p>Here's the message publisher application code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amqp = <span class="hljs-built_in">require</span>(<span class="hljs-string">"amqplib"</span>);
<span class="hljs-keyword">const</span> url = <span class="hljs-string">"amqp://localhost"</span>; <span class="hljs-comment">// Replace with your RabbitMQ server URL</span>
<span class="hljs-keyword">const</span> queue = <span class="hljs-string">"queue"</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">msg</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(url);
    <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();

    <span class="hljs-keyword">await</span> channel.assertQueue(queue);
    <span class="hljs-keyword">await</span> channel.sendToQueue(queue, Buffer.from(msg));

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent to <span class="hljs-subst">${queue}</span>: <span class="hljs-subst">${msg}</span>`</span>);

    <span class="hljs-keyword">await</span> channel.close();
    <span class="hljs-keyword">await</span> connection.close();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Failed to send message:"</span>, err);
  }
}

sendMessage(<span class="hljs-string">"Hello, world!"</span>);
</code></pre>
<p>Here is the output of the code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/msg-queue.PNG" alt="Executed Node JS code" width="600" height="400" loading="lazy"></p>
<h2 id="heading-additional-info">Additional info</h2>
<p>So far, we have completed this tutorial on message queueing and its role in facilitating seamless communication across various systems. To further improve your skillset, here are some additional best practices that should be implemented when building complex services:</p>
<ul>
<li><p>Rate limiting</p>
</li>
<li><p>Load balancing</p>
</li>
<li><p>Application monitoring and logging</p>
</li>
<li><p>Continuous integration and deployment</p>
</li>
</ul>
<h2 id="heading-summary">Summary</h2>
<p>We've highlighted the importance of message brokers and how to implement message queueing in a backend application.</p>
<p>Feel free to check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Your Node.js App on Azure ]]>
                </title>
                <description>
                    <![CDATA[ The advent of cloud computing marked a turning point in the field of technology. It provides easier access for users across the globe to web and mobile applications and services.  Modern-day computing services also provide a wide range of features wh... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-node-js-app-on-azure/</link>
                <guid isPermaLink="false">66bb58c75a83db22bea9843b</guid>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Hosting ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 17 Jul 2024 11:56:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/awsP.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The advent of cloud computing marked a turning point in the field of technology. It provides easier access for users across the globe to web and mobile applications and services. </p>
<p>Modern-day computing services also provide a wide range of features which make web apps easier to use and more efficient. So it's important for developers to have a basic understanding of how the cloud works.</p>
<p>This article is a beginner's guide to deploying backend applications to the cloud. We'll use the Azure platform as our cloud infrastructure and Node.js/Express for the backend web application. Before we go on, here are a few requirements:</p>
<ul>
<li>Basic understanding of cloud computing (you can check out <a target="_blank" href="https://dev.to/oluwatobi2001/introduction-to-cloud-computing-the-models-benefits-risks-implementation-and-popular-tools-2loh">this article</a> to learn more about that).</li>
<li>Knowledge of JavaScript.</li>
<li>VS Code.</li>
</ul>
<p>With that, let's get started.</p>
<h2 id="heading-introduction-to-azure">Introduction to Azure</h2>
<p>Azure is a cloud computing platform developed by Microsoft that acts as a server for deploying and hosting web applications, databases, file storage, and so on. </p>
<p>Compared to other cloud computing services, it is quite beginner-friendly and has an actively growing user base. Let’s explore the Azure portal.</p>
<h2 id="heading-how-to-set-up-azure-account">How to Set Up Azure Account</h2>
<p>Signing up on the Azure platform is the first step to hosting your application.   First, navigate to <a target="_blank" href="https://azure.microsoft.com/en-us/get-started/azure-portal">the website</a> and complete the signup process.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Azure sign in page</em></p>
<p>After signing up, you'll have access to the management console of the Azure application where all our activities can be carried out.</p>
<p>Before we go on, here are some of the services we'll be getting familiar with on this platform.</p>
<ul>
<li>Azure Resource groups</li>
<li>Azure app services</li>
<li>Storage accounts</li>
<li>SQL databases</li>
<li>Virtual networks</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/serc3.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Azure services</em></p>
<p>Congratulations on successfully creating your Azure account.</p>
<h2 id="heading-deployment-options-on-azure">Deployment Options on Azure</h2>
<p>As a cloud computing platform, Azure boasts of its wide versatility. Depending on your skill level or preference, you can deploy web applications to Azure via the following options:</p>
<ul>
<li>Azure CLI</li>
<li>Azure Virtual machines</li>
<li>Azure Functions</li>
<li>Azure Kubernetes Service</li>
<li>Azure Storage.</li>
<li>Azure DevOps</li>
<li>Azure portal service</li>
</ul>
<p>We'll utilize the Azure portal service for this tutorial and use its VS Code integration to deploy a simple Node.js application to the Azure cloud.</p>
<h2 id="heading-how-to-set-up-the-backend-application">How to Set Up the Backend Application</h2>
<p>We'll create our web application using Node.js via the command line and Visual Studio Code.</p>
<p>Firstly, navigate to the folder where your app will be created and initialize a Node project by executing <code>npm init</code></p>
<p>Next, initialize the app by installing the <code>Express</code> framework. This can be done via <code>npm i express</code>. </p>
<p>Go on and paste the sample code for this tutorial:</p>
<pre><code><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();

app.use(express.json());

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.send(<span class="hljs-string">"Hello, World"</span>);
});

app.listen(process.env.PORT || <span class="hljs-number">5000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server is running on port "</span> + (process.env.PORT || <span class="hljs-number">5000</span>));
});
</code></pre><p>The code above outputs <code>Hello World</code> whenever it is executed.</p>
<h2 id="heading-application-deployment">Application Deployment</h2>
<p>The backend code we wrote in the preceding paragraph will be deployed to Azure via the use of Azure’s VS Code extension.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/webVs.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>VS Code homepage</em></p>
<p>Navigate to the Extensions tab, search for Azure App Services and install the extension. On successful installation, an Azure widget will appear on your taskbar where you can sign in to the Azure cloud.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/azure-app-service.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Extensions marketplace</em></p>
<p>Subsequently, we'll be creating a cloud-based web application in which our Node.js code will later be deployed.</p>
<p>On the Azure resources tab, clicking the <code>plus</code> icon will display a drop-down menu where various development options can be seen. We'll be clicking on the Azure app services option.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/res-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Azure drop down menu</em></p>
<p>After clicking that, a prompt will pop up asking for a unique name for the cloud application. In my case, I went with newApp777.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/newa7.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>creating a web application</em></p>
<p>However, you can use any other name you so wish. Subsequently, you will need to select the backend language of your choice. Any version of Node.js will be compatible with our application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/newStack.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>web stacks available</em></p>
<p>Also, the F1 service option will be used for this tutorial. However, you can pick anyone you so desire.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/newTier.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Various Azure tiers</em></p>
<p>On successful completion, your application will be created on the Azure portal.</p>
<p>Now to the crux of the matter. Let's install our Node.js code on this web application. </p>
<p>We'll click on the code folder which provides us with options to automatically deploy our code to an Azure web app service.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-35.png" alt="Image" width="600" height="400" loading="lazy">
<em>Deployment dropdown menu</em></p>
<p>As soon as this is done, the list of the cloud servers on your Azure account will be shown. You can then select the new app we just created.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/sear.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>app deployment</em></p>
<p>Your backend code should then be deployed on the NewApp cloud server we created. On successful completion, you'll receive a success message with a link to your cloud application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/pro.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>command prompt interface</em></p>
<p>Congratulations, you have successfully hosted your first web application. Navigate <a target="_blank" href="https://newapp777.azurewebsites.net/">here</a> to see the hosted application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/wevpage.PNG" alt="Azure app" width="600" height="400" loading="lazy">
<em>The application webpage</em></p>
<h2 id="heading-additional-information">Additional Information</h2>
<p>So far, we have covered the basics of deploying an application via the use of VS code extensions on Azure portal services. As you progress in the field of cloud computing, other interesting fields can also be explored such as:</p>
<ul>
<li>App monitoring with Azure Monitor.</li>
<li>Azure app networking essentials.</li>
<li>Azure MySQL database integration.</li>
<li>Node JS serverless functions deployment.</li>
</ul>
<p>You can also interact with me on my blog and check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Enhance Embedded Links in React with Microlinks ]]>
                </title>
                <description>
                    <![CDATA[ The web has evolved from rigid color coding and 2D rendering to an era of complex, aesthetically pleasing animations and 3D rendering options. There have also been integrations with new technologies, such as virtual reality tools and frameworks, to i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-enhance-embedded-links-in-react-with-microlinks/</link>
                <guid isPermaLink="false">66bb58ca7b4b3dfb6852274b</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Tue, 18 Jun 2024 02:56:25 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/microl.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The web has evolved from rigid color coding and 2D rendering to an era of complex, aesthetically pleasing animations and 3D rendering options. There have also been integrations with new technologies, such as virtual reality tools and frameworks, to improve the user experience.</p>
<p>In this article, you'll learn how to optimize embedded links in your front-end development projects to meet your desired specifications. </p>
<p>The inspiration for this article came from a problem I encountered while creating a portfolio site and having issues embedding external sites—until I discovered an efficient tool to help.</p>
<p>To fully grasp this tutorial, there are some of the prerequisites:</p>
<ul>
<li>A good knowledge of JavaScript.</li>
<li>Familiarity with React JS and npm package installation.</li>
<li>Proficiency in CSS.</li>
</ul>
<p>Let's get started!</p>
<h2 id="heading-the-concept-of-micro-linking">The Concept of Micro-linking</h2>
<p>Micro-linking entails embedding a link to an external website within a default web page. Embedding links are different from the default HTML  <code>“alt href”</code>  attributes commonly used by web developers.</p>
<p>This concept also entails extracting relevant site metadata, information and relevant images from the embedded external site link. This contributes to providing more knowledge about the external website in question.</p>
<p>This feature isn’t all new as it's commonly used among high-end blog posts, video streaming sites and e-commerce sites. This feature is also utilized by site owners to customize how their site information is viewed when embedded in advertisement sites.</p>
<h2 id="heading-how-does-micro-linking-work">How Does Micro-linking Work?</h2>
<p>Ordinarily, embedding a URL using plain HTML code doesn’t generate any image or text preview. However, this isn’t the case for micro-links. This occurs due to the use of an application programming interface to extract relevant info from the site being referenced and then outputting it to the developer in JSON format for easy customization and usage. </p>
<p>There are quite a lot of micro-linking services available commercially. Some examples are <a target="_blank" href="https://embed.ly/">Embedly</a>, <a target="_blank" href="https://ogp.me/">Open Graph</a> protocol, <a target="_blank" href="https://microlink.io/">microlink.io</a>, and so on.</p>
<h2 id="heading-introduction-to-the-microlink-package">Introduction to the Microlink Package</h2>
<p>In this tutorial, we'll create a site that uses a Node package known as Microlink to generate previews. Details regarding URL customization will also be illustrated. </p>
<p>This is customization allows developers to easily extract relevant link previews from the Microlink site, skipping the hassle of interacting with the website interface. </p>
<p>For further learning, the library has a rich documentation site which can be accessed <a target="_blank" href="https://microlink.io/docs/sdk/integrations/react">here</a>.</p>
<h2 id="heading-how-to-set-up-your-project">How to Set Up Your Project</h2>
<p>To build the link preview site, we'll utilize the React Vite tool. Entering the command <code>npm create-vite-app@latest links</code> immediately spins up a folder named <code>latest links</code> which we'll use in building this project.</p>
<p>Also, the <code>microlink</code> package needs to be installed. To do that, navigate to the command line and run the <code>npm i @microlinks/react</code> command.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>First of all, we'll be create the default JSX functional component for this project.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;&gt;</span>
<span class="hljs-tag">&lt;/&gt;</span></span>
)
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre><p>Next, we'll be import and initialize the installed <code>microlink</code> library:</p>
<pre><code><span class="hljs-keyword">import</span> Microlink <span class="hljs-keyword">from</span> <span class="hljs-string">'@microlink/react'</span>
</code></pre><p>After that, we can initialize the package within the App function:</p>
<pre><code><span class="hljs-keyword">return</span> (
<span class="xml"><span class="hljs-tag">&lt;&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Microlink</span>
<span class="hljs-attr">url</span>= <span class="hljs-string">" https://tobilyn77.hashnode.dev/nodejs-clustering-and-load-balancing-comprehensive-overview "</span>  /&gt;</span>
<span class="hljs-tag">&lt;/&gt;</span></span>
)
</code></pre><p>The URL variable I included is a link to an external site I intend to preview on my local site. This can be changed to whichever site you would like to preview.</p>
<p>On running this, you should see something similar to this.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/micro1-1.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>microlink project webpage</em></p>
<p>We have successfully set up a micro-link in our application. But that’s not all, the power of the package is enormous, providing a level of flexibility in controlling the layout and size of the micro-links.</p>
<h3 id="heading-size-tweaking">Size Tweaking</h3>
<p>Size tweaking simply involves adjusting the size or dimensions of a variable to suit different specifications. In this case, we'll adjust the size of the embedded links. </p>
<pre><code>&lt;Microlink
url= <span class="hljs-string">"https://tobilyn77.hashnode.dev/nodejs-clustering-and-load-balancing-comprehensive-overview"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Microlink</span>
<span class="hljs-attr">url</span>= <span class="hljs-string">"https://tobilyn77.hashnode.dev/nodejs-clustering-and-load-balancing-comprehensive-overview"</span>  <span class="hljs-attr">size</span>=<span class="hljs-string">"small"</span>/&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2024/06/micro2.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>micro-links with different sizes</em></p>
<p>The code above specifies the size of the micro-link to be rendered. If the size is indicated to be <code>small</code>, the dimension of the micro-link gets altered. It also allows for large and medium sizes, and by default, the medium size is what is usually seen when no size dimension is specified.</p>
<p>Also, the <code>microlink</code> self-enclosing tag allows for CSS styling. This can be achieved by including the style variable within the <code>microlink</code> tag.</p>
<pre><code>&lt;Microlink
url= <span class="hljs-string">"https://tobilyn77.hashnode.dev/nodejs-clustering-and-load-balancing-comprehensive-overview"</span>
style= {{<span class="hljs-attr">color</span>: <span class="hljs-string">'red'</span>}} /&gt;
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2024/06/micro3.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>micro-link with the color set to red</em></p>
<p>As you can see in the code above, the <code>microlink</code> was styled with the color red and that reflected in the output. Other CSS styling can also be applied to give users an aesthetic feel to your site.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learned link previewing via the <code>microlink</code> package.</p>
<p>Feel free to drop any questions or comments in the comment box below. You can also interact with me on my blog and check out my other articles  <a target="_blank" href="https://www.freecodecamp.org/news/p/cedba683-793c-4c78-85d9-c46647c75b71/linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Resilient Microservice Systems – SOLID Principles for Microservices ]]>
                </title>
                <description>
                    <![CDATA[ We are in the era of transformative technology with several innovations springing up to improve service delivery and enhance customers’ satisfaction. More so is the introduction of microservices and other distributed systems into the software industr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/solid-principles-for-microservices/</link>
                <guid isPermaLink="false">66bb58d40da5b03e481107da</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ solid ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Tue, 21 May 2024 09:56:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/solid.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We are in the era of transformative technology with several innovations springing up to improve service delivery and enhance customers’ satisfaction. More so is the introduction of microservices and other distributed systems into the software industry to revolutionize enterprise application development.</p>
<p>Its introduction has helped to solve problems associated with the age-long monolithic software development approach, overcoming its cons and achieving scalability.</p>
<p>In this article, I hope to dive deep into what microservices entail and highlight its significant use cases. Also, I will dive deep into the SOLID principles and other best practices necessary to build efficient microservices. With that, let's get started.</p>
<p>First of all, what is a microservice?</p>
<h2 id="heading-what-is-a-microservice">What is a Microservice?</h2>
<p>This is a type of system architecture in which an application gets structured as a confluence of several independent, loosely coupled independent services. This ensures that each aspect of the overall application gets managed individually and still functions irrespective of the current state of other independent services. These independent servers still allow for information sharing over a given network.</p>
<p>It actively mirrors the distributed system model which segregates the various computers on a network and shares resources amongst them. The adoption of this model by big enterprises has been seen to be advantageous as it has greatly reduced server downtime, minimized costs and maintained efficiency.</p>
<p>The microservice system architecture also provides an upper hand to these firms as it rapidly provides scaling opportunities in case of a spike in user visits. The scaling could either be horizontal which involves activating multiple servers to handle user requests or vertical which involves increasing the CPU power of the server to efficiently handle user requests.</p>
<p>Unlike conventional monolithic systems, microservice best practices deviate slightly from the conventional ACID principles designed for related databases. Hence it's important to learn about best practices and principles which serve as a basis for building resilient microservices. </p>
<p>This will take us into the world of the SOLID principles.  The solid principles form the general basis of object-oriented programming and design but have been adapted in the context of building resilient microservices.  But what does SOLID represent?</p>
<ul>
<li>Single Responsibility Principle</li>
<li>Open-Close Principle</li>
<li>Liskov Substitution Principle</li>
<li>Interface Segregation Principle</li>
<li>Dependency Inversion Principle</li>
</ul>
<p>Let's discuss these in detail.</p>
<h2 id="heading-single-responsibility-principle">Single Responsibility Principle</h2>
<p>This principle states that each service in the grand microservice architecture is responsible for a single functionality or possesses a single reason to change. This implies that the service in question is solely and wholly built to fulfil a specific application functionality and it is done cohesively. </p>
<p>This feature provides it with the liberty to scale bigger to effectively deliver on that given functionality. This forms the baseline for microservices development as it reduces the interference of several services due to service interdependency which is a side effect of monolithic applications.</p>
<h2 id="heading-open-close-principle">Open-Close Principle</h2>
<p>This principle was initially applied for object-oriented programming but is now also adapted for microservices development. It entails that services created within the overall microservice architecture are open to extension with additional service functionalities and communication via the services interface but should be closed to code modification. </p>
<p>This principle is necessary as code modification affects service functionality and stability and also serves as a risk for introducing bugs to the existing code which can ultimately cause errors in system function.</p>
<p>To ensure this, features such as code versioning allow for newer versions of an existing service to be created and deployed without affecting the older versions' functionality and maintain the system's efficiency. Also ensuring the implementation of APIs on each service and the concept of dependency inversion (which will be discussed in the subsequent section) helps to achieve this principle.</p>
<h2 id="heading-liskov-substitution-principle">Liskov Substitution Principle</h2>
<p>This principle is named after its originator, Barbara Liskov. It means that services built within complex microservice architecture can and should be easily substituted or replaced with no or minimal side effects to the entire microservice architecture. This feature also enables developers to build modular microservices applications.</p>
<p>It also enables the execution of the dependency inversion principle which will be discussed in subsequent paragraphs. Achieving this principle involves structuring the microservice architecture with the use of interfaces and classes which allows for the reuse and light coupling of services.</p>
<h2 id="heading-interface-segregation-principle-isp">Interface Segregation Principle (ISP)</h2>
<p>This principle builds on the Liskov substitution principle and it simply advocates for ensuring that interfaces used for each service are specific for the users who interact with them solely. This ensures that the interface delivers the specific function intended by the service created. This would in turn minimize service interdependency among various services and ensure service application autonomy, enabling it to achieve the desired scalability and overall efficiency possible.</p>
<p>This, alongside the Liskov substitution principle, allows for seamless microservice application evolution over a given cycle. To achieve this, it is important to ensure a minimal reliance of the service on external dependencies and also declare explicit and distinct functions for each service.</p>
<h2 id="heading-dependency-inversion-principle">Dependency Inversion Principle</h2>
<p>This principle negates the age-long tradition in which high-level modules and services tend to depend on smaller low-level services to achieve the necessary efficiency and correctly perform their designated function. It now implies that the high-level services/modules should not depend on anything from the low-level services and both should only interact based on the existing abstraction. In our case, this implies that the interfaces already discussed earlier.</p>
<p>This principle, in line with the other principles, permits easy scaling of each service or module in question and also allows for service reuse or substitution whenever such is needed. This principle has also revolutionized the way applications get built as they now delineate the functions and autonomy of each service in the application.</p>
<h2 id="heading-additional-information">Additional Information</h2>
<p>So far, we have shed light on the SOLID microservices design principles. However, other additional tips which could be of great help when building microservices include:</p>
<h3 id="heading-availability-over-consistency-principle">Availability Over Consistency Principle</h3>
<p>This principle is based on the CAP theorem (consistency, availability and partition tolerance. Hypothetically, a system should have all these components implemented and fully functional but in reality, this isn’t so. Ensuring these works often results in network lags, which affects system efficiency, resulting in the need for tradeoffs among these components.</p>
<p>In the case of microservices development, the need for a service to be continually consistent in providing an updated response to a request gets overridden by the need for the service to be available with minimal downtime. Eventually, the overall microservice consistency is achieved during a given period via conflict resolution techniques and other consensus protocols.</p>
<h3 id="heading-easy-deployability-principle">Easy Deployability Principle</h3>
<p>Unlike conventional monolithic applications, deploying microservices is a bit complex as it requires ensuring seamless communication across various deployments. However, this can be achieved by mastery of some techniques.</p>
<p>Firstly, it's important to possess knowledge of containerization and containerization tools such as Docker. Additionally, knowledge of orchestration tools like Kubernetes is an additional advantage. Adequate knowledge of Infrastructure as Code tools such as Terraform also helps as it gives the developers great control over the application and allows for easy versioning. Provision of monitoring and observability tools to help detect any anomaly in the operations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learned essentially about the principles and other best practices to have in mind when building microservices and other distributed applications.</p>
<p>Feel free to drop comments and questions in the box below, and also check out my other articles <a target="_blank" href="https://linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Your Database – Optimization Principles and Best Practices ]]>
                </title>
                <description>
                    <![CDATA[ Databases are an integral component of building applications, whether web, desktop or mobile. They symbolically serve as the mitochondria of the application, as their primary function is to manage data. Database management is a critical skill a devel... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/database-optimization-principles/</link>
                <guid isPermaLink="false">66bb58c3965d5c9ed5487ba2</guid>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Fri, 10 May 2024 15:21:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/Acid.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Databases are an integral component of building applications, whether web, desktop or mobile. They symbolically serve as the mitochondria of the application, as their primary function is to manage data.</p>
<p>Database management is a critical skill a developer must possess in building scalable applications that have a high level of efficiency. If not handled properly, it can result in data loss and mismanagement on the part of the database developer.</p>
<p>Hence, databases must be structured and built with the users in mind and built utilizing the best practices available.</p>
<p>This article aims to highlight general principles of database best practices and also explain each peculiarity. But before we discuss that in detail, let’s review what database transactions are all about.</p>
<h2 id="heading-what-are-database-transactions">What are Database Transactions?</h2>
<p>Database transactions are simply groups of operations which can be termed as a unit of a work process performed on a database within a database management system. </p>
<p>It encompasses basic operations such as CRUD operations to more advanced operations such as database indexing, caching, and normalization.</p>
<p>With so many users performing many transactions at the same time, it’s important to ensure that the database is concurrency-enabled to prevent data interference between two or more users accessing the same resource. </p>
<p>Hence, there is the need for the ACID principle.  What then does ACID represent?</p>
<ul>
<li>Atomicity</li>
<li>Consistency</li>
<li>Isolation</li>
<li>Durability</li>
</ul>
<p>Subsequently, we will be discussing each point in detail. First on our list is atomicity.</p>
<h2 id="heading-what-is-the-database-atomicity-principle">What is the Database Atomicity Principle?</h2>
<p>What does database atomicity entail? The atomicity of a database simply means that a database operation can’t be broken down further as a unit. This means that the database operation or transactions gets executed completely, and in case any error comes up during the execution process, the entire operation gets completely cancelled, preventing room for partial operation execution.</p>
<p>If the database isn’t atomic, this can result in the provision of misleading incomplete data and ultimately result in entire system chaos. How does the database ensure atomicity? It does this by creating a copy of the existing database before the operation gets executed and then initiates a crash recovery and backup restoration operation in the event of an operation failure.</p>
<p>It is also important to note that other database principles such as consistency and durability rely on the need for the database to be atomic to be truly fulfilled.</p>
<p>Having discussed this, let’s move on to the database consistency principle.</p>
<h2 id="heading-what-is-the-database-consistency-principle">What is the Database Consistency Principle?</h2>
<p>This principle entails that the database has certain constraints, cascades, triggers and other requirements in place, which needs to be fulfilled while making changes to an established database. Failure to fulfill this requirement will lead to consistency errors, returning the database to its previous stable state.</p>
<p>Also, consistency as a principle ensures that the data updated by a user is made available as the latest version of the data in the database to all users who desire to read the database. Having this in place eliminates the occurrence of inconsistencies and aids faster information retrieval.</p>
<p>Understanding what it means for a database to be consistent involves ensuring the operation performed on the database passes the integrity check before being successfully executed. Having exhausted this in detail, let's discuss the database isolation principle.</p>
<h2 id="heading-what-is-the-database-isolation-principle">What is the Database Isolation Principle?</h2>
<p>Why should we isolate a database and how does one make a database operation independent from other database operations?</p>
<p>Isolation is necessary in a database management system to ensure that the user's access to information on the database is not interfered with by other concurrent transactions undertaken by other users on the database. To enforce this, the use of isolation levels in each database operation helps to preserve information integrity.</p>
<p>To effectively guarantee the database integrity, specific database isolation levels must be used. Here are some of the isolation levels ranked in order of hierarchy:</p>
<ul>
<li>Read uncommitted</li>
<li>Read committed</li>
<li>Repeatable read</li>
<li>Serializability</li>
</ul>
<h3 id="heading-read-uncommitted-isolation-level">Read Uncommitted Isolation Level</h3>
<p>The read uncommitted database isolation level allows other users to have access to read current database transactions which has not yet been completely or successfully executed. It allows access to read what is being referred to as dirty read, which is one of the data inconsistencies that can be seen. This level of data isolation isn’t advised.</p>
<h3 id="heading-read-committed-isolation-level">Read Committed Isolation Level</h3>
<p>This database isolation level disallows other users to read or have access to a database transaction that has not yet been committed. Hence it prevents other users from seeing, updating or overwriting it until it has been completely executed.</p>
<h3 id="heading-repeatable-read-isolation-level">Repeatable Read Isolation Level</h3>
<p>This isolation level exclusively isolates a transaction from other transactions occurring concurrently, preventing other users access to read and update the transactions.</p>
<h3 id="heading-serializability-isolation-level">Serializability Isolation Level</h3>
<p>This is the highest level of data isolation and is referred to as the strictest level. It isolates the multiple transactions performed concurrently and executes them efficiently as they are executed serially. It also prevents database inconsistencies.</p>
<p>Without these levels in place, inconsistent database mishaps such as dirty reads, non-repeatable reads, phantom reads and many others may be experienced. With this, let's move on to the last point about database durability and discuss it in detail.</p>
<h2 id="heading-what-is-the-database-durability-principle">What is the Database Durability Principle?</h2>
<p>What does it imply when we describe a database as durable and how do we ensure the durability of a database? Durability as it sounds is a principle which ensures that databases have a high level of immortality.</p>
<p>Irrespective of any adverse outcomes that the database management system might face such as outages and crashes, there shouldn't be any loss of database information.</p>
<p>How do databases try to achieve this? The database creates a transactional log that contains the recorded data before any new operation gets executed. In the event of any of these adverse events, the transaction log serves as the backup store, ensuring that the database info is well preserved up to the point before the operation occurred, thereby mitigating against data breaches and loss.</p>
<p>We'll also highlight other helpful database operations best practices that can also be implemented.</p>
<h2 id="heading-other-database-operations-best-practices">Other Database Operations Best Practices</h2>
<p>The BASE principle, which is more suited for NoSQL databases such as MongoDB, Redis, and Cassandra, and so on. It entails a database to be:</p>
<ul>
<li>Basically available</li>
<li>Existing in a soft state</li>
<li>And be eventually consistent.</li>
</ul>
<h3 id="heading-basically-available">Basically Available</h3>
<p>This entails that the database prioritizes the availability of the database operations over consistency and concurrency. This is quite applicable to distributed systems which rely on a high level of efficiency to function effectively.</p>
<h3 id="heading-soft-state">Soft State</h3>
<p>This ensures easy flexibility of the database, allowing for size scaling, operations and increased concurrency for optimal database performance at all times. This allows the data to maintain resiliency.</p>
<h3 id="heading-eventually-consistent">Eventually Consistent</h3>
<p>This entails that, irrespective of how the transactions get executed in the sequences, it eventually achieves efficient consistency. This is achieved by conflict resolution and reconciliation. This eventually contributes to the building of a resilient data system.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learned essentially about optimizing database operations and their efficiency using the ACID principle and other best practices available.</p>
<p>Feel free to drop comments and questions in the box below, and also check out my other articles <a target="_blank" href="https://www.freecodecamp.org/news/p/2a9a2ef7-b659-4655-97ce-fea0f3a9f668/linktr.ee/tobilyn77">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Prevent Web API Attacks with Data Validation – Web API Security Guide ]]>
                </title>
                <description>
                    <![CDATA[ Adequate data protection and user confidentiality are key responsibilities for web developers. Hence, it is important to ensure the highest possible security while building API endpoints. The act of application security is a shared responsibility amo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/web-api-security-guide/</link>
                <guid isPermaLink="false">66bb58d7965d5c9ed5487ba4</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Validation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Wed, 03 Apr 2024 09:13:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/apidat.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Adequate data protection and user confidentiality are key responsibilities for web developers. Hence, it is important to ensure the highest possible security while building API endpoints.</p>
<p>The act of application security is a shared responsibility amongst the client and server developers and negligence of one’s role can be disastrous. <a target="_blank" href="https://www.statista.com/statistics/1307426/number-of-data-breaches-worldwide/#:~:text=During%20the%20fourth%20quarter%20of,concerns%20of%20company%20leaders%20worldwide.">Statistics</a> show that data breaches in 2023 resulted in exposure of over 8 million data records worldwide.</p>
<p>In this article, I'll be highlighting key areas of API security, which involves data validation.  This concept is quite crucial in helping you protect your API from web attacks via malicious user data. This tutorial is well-suited for all backend developers regardless of years of experience.</p>
<p>To be able to follow this tutorial, here are some prerequisites:</p>
<ul>
<li>Knowledge of Node.js</li>
<li>Knowledge of npm and package installation</li>
</ul>
<p>With that in place, let’s get started.</p>
<h2 id="heading-how-does-data-validation-work">How Does Data Validation Work?</h2>
<p>First of all, what is data validation? Data validation simply entails ensuring the accuracy and reliability of the data received from external sources before onward data processing. </p>
<p>It is a key component of web API security as it is essential for preventing the occurrence of web injection attacks, SQL attacks and NoSQL attacks. To know more about these, you can check this <a target="_blank" href="https://owasp.org/www-community/Injection_Flaws#:~:text=Description,connected%20to%20the%20vulnerable%20application.">link</a>.</p>
<p>Note that data validation is needed but not limited to the following backend operations.:</p>
<ul>
<li>User login and sign up</li>
<li>Response query</li>
<li>Updating server databases</li>
</ul>
<p>All these can be used as avenues by mischievous black hat hackers to gain access to the server database and obtain sensitive user details or even wreak havoc by formatting the entire database.</p>
<h2 id="heading-popular-data-validation-tools">Popular Data Validation Tools</h2>
<p>So far, there are lot of tools that can help the programmer achieve efficient data validation in API development. </p>
<p>They help you avoid reinventing the wheel of using long regex code to validate data. They provide a whole lot of features, including error handling and validation customization functionalities.  </p>
<p>Some of these tools include:<br>•    <a target="_blank" href="https://joi.dev">Joi</a><br>•    <a target="_blank" href="https://zod.dev/">Zod</a><br>•    <a target="_blank" href="https://www.npmjs.com/package/yup">Yup</a><br>•    <a target="_blank" href="https://ajv.js.org/">AJv</a><br>•    <a target="_blank" href="https://valibot.dev/">Valibot</a><br>•    <a target="_blank" href="https://www.npmjs.com/package/validatorjs">Validator.js</a><br>•    <a target="_blank" href="https://docs.superstructjs.org/guides/02-validating-data">Superstruct</a></p>
<p>To further shed light on these tools, we'll compare some of the most popular data validation tools mentioned above.</p>
<h2 id="heading-pros-and-cons-of-data-validation-tools">Pros and Cons of Data Validation Tools</h2>
<p>To further enlighten you about these JavaScript validation tools, I will be highlighting some pros and cons of three of these popular JavaScript validation tools.</p>
<h3 id="heading-joi">Joi</h3>
<h6 id="heading-pros">Pros</h6>
<ul>
<li>It has a strong, large user community and development support</li>
<li>It has built-in capabilities to handle complex validations</li>
</ul>
<h6 id="heading-cons">Cons</h6>
<ul>
<li>It’s syntax is quite verbose</li>
</ul>
<h3 id="heading-zod">Zod</h3>
<h6 id="heading-pros-1">Pros</h6>
<ul>
<li>It is easily compatible with Typescript projects</li>
<li>It has efficient error-handling capabilities</li>
</ul>
<h6 id="heading-cons-1">Cons</h6>
<ul>
<li>Async validation isn’t supported.</li>
</ul>
<h3 id="heading-yup">Yup</h3>
<h6 id="heading-pros-2">Pros</h6>
<ul>
<li>It mainly uses declarative syntax to set its validation tool which confers its simplicity</li>
<li>It has a comparable fast performance.</li>
</ul>
<h6 id="heading-cons-2">Cons</h6>
<ul>
<li>It doesn’t provide customization features</li>
<li>It has limited ability to handle complex validations</li>
</ul>
<p>For the purpose of this tutorial, we'll use Joi as our data validation tool.</p>
<h2 id="heading-introduction-to-joi">Introduction to Joi</h2>
<p>Joi is a simple and efficient JavaScript-based data validation tool that is based on the schema-type configuration.</p>
<p>It has built-in capabilities for validating the occurrence of data in various forms, but not limited to Booleans, strings, functions and intervals. It can also handle complex validation operations.</p>
<p>Additionally, it provides minimal caching functionalities. More information about the tool can be found <a target="_blank" href="https://joi.dev/api/?v=17.12.2">here</a>.</p>
<h2 id="heading-how-to-set-up-joi">How to Set Up Joi</h2>
<p>In this section, we'll set up Joi in our local environment. To install Joi, navigate to the code folder via the command line and run this:</p>
<pre><code class="lang-bash">npm i joi
</code></pre>
<p>A message confirming successful installation should be displayed. With that completed, we can demonstrate the power of Joi in validating user registration in our demo API.</p>
<h2 id="heading-demo-project">Demo Project</h2>
<p>In this project, you'll use Joi to validate the input received from the client with the intent to sign up on the server. The default code for the user sign-up function for the Node.js application can be found <a target="_blank" href="https://github.com/oluwatobi2001/location-backend/blob/master/Controller/Authentication.js">here</a>.</p>
<p>Go on and import the installed Joi package into your code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">"joi"</span>);
</code></pre>
<p>Before writing our signup controller, we'll initialize the Joi library within the code file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> SignUpSchema = Joi.object({});
</code></pre>
<p>In this project, we'll validate the email, password and username parameters received from the client.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> SignUpSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({
        <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>,
        <span class="hljs-attr">tlds</span>: {
            <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>]
        }
    }),
    <span class="hljs-attr">username</span>: Joi.string().alphanum().min(<span class="hljs-number">3</span>).max(<span class="hljs-number">15</span>).required(),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});
</code></pre>
<p>The email parameter object ensures that the email address is a string, and the domain site is limited to .com and .net, disallowing other forms of domains.</p>
<p>For the username parameter, it ensures that it is a string containing both letters and numbers with a minimum character count of 3 and a maximum character count of 15. The required function ensures that these conditions must be met or the entire request won't be validated.</p>
<p>The password parameter ensures that the password supplied is in a string format with a minimum character count of 8, and it is also required.</p>
<p>To apply it to our endpoints, we include this within the controller function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { error, value } = SignUpSchema.validate(req.body, { <span class="hljs-attr">abortEarly</span>: <span class="hljs-literal">false</span> });
<span class="hljs-keyword">if</span> (error) {
    res.status(<span class="hljs-number">400</span>).json(error.details);
    <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>This function gets executed before inserting the user details into the database. The schema tries to validate the received input and then proceeds to the database if successfully validated.</p>
<p>The <code>abortEarly</code> feature is included to allow for all parameters to be assessed. All the errors will be displayed if there is any.</p>
<p>The above can also be replicated in the Login controller function. You can also check out the <a target="_blank" href="https://joi.dev/api/?v=17.12.2">documentation</a> for other examples of complex validation options using Joi.</p>
<p>The final code for the project is displayed below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"jsonwebtoken"</span>);
<span class="hljs-keyword">const</span> userSchema = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../Schema/User"</span>);
<span class="hljs-keyword">const</span> Joi = <span class="hljs-built_in">require</span>(<span class="hljs-string">"joi"</span>);
<span class="hljs-keyword">const</span> bcrypt = <span class="hljs-built_in">require</span>(<span class="hljs-string">"bcrypt"</span>);
<span class="hljs-keyword">const</span> { createNewColumn, checkRecordsExists, insertRecord } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/sqlSchemaFunction'</span>);

<span class="hljs-keyword">const</span> generateAccessToken = <span class="hljs-function">(<span class="hljs-params">use</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> jwt.sign({ <span class="hljs-attr">userID</span>: use }, process.env.JWT, { <span class="hljs-attr">expiresIn</span>: <span class="hljs-string">"1d"</span> });
}

<span class="hljs-keyword">const</span> SignUpSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({ <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">tlds</span>: { <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>] } }),
    <span class="hljs-attr">username</span>: Joi.string().alphanum().min(<span class="hljs-number">3</span>).max(<span class="hljs-number">15</span>).required(),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});

<span class="hljs-keyword">const</span> loginSchema = Joi.object({
    <span class="hljs-attr">email</span>: Joi.string().email({ <span class="hljs-attr">minDomainSegments</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">tlds</span>: { <span class="hljs-attr">allow</span>: [<span class="hljs-string">'com'</span>, <span class="hljs-string">'net'</span>] } }),
    <span class="hljs-attr">password</span>: Joi.string().min(<span class="hljs-number">8</span>).required()
});

<span class="hljs-keyword">const</span> register = <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> email = req.body.email;
    <span class="hljs-keyword">const</span> password = req.body.password;

    <span class="hljs-keyword">if</span> (!email || !password) {
        res.status(<span class="hljs-number">400</span>).json(<span class="hljs-string">"Please supply the email or password"</span>);
        <span class="hljs-keyword">return</span>; 
    }

    <span class="hljs-keyword">const</span> { error, value } = SignUpSchema.validate(req.body, { <span class="hljs-attr">abortEarly</span>: <span class="hljs-literal">false</span> });
    <span class="hljs-keyword">if</span> (error) {
        res.status(<span class="hljs-number">400</span>).json(error.details);
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">const</span> salt = <span class="hljs-keyword">await</span> bcrypt.genSalt(<span class="hljs-number">10</span>);
    <span class="hljs-keyword">const</span> hashedPassword = <span class="hljs-keyword">await</span> bcrypt.hash(password, salt);
    <span class="hljs-keyword">const</span> user = {
        <span class="hljs-attr">username</span>: req.body.username,
        <span class="hljs-attr">email</span>: email,
        <span class="hljs-attr">password</span>: hashedPassword
    };

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> userAlreadyExists = <span class="hljs-keyword">await</span> checkRecordsExists(<span class="hljs-string">"users"</span>, <span class="hljs-string">"email"</span>, email);
        <span class="hljs-keyword">if</span> (userAlreadyExists) {
            res.status(<span class="hljs-number">400</span>).json(<span class="hljs-string">"Email must be unique"</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">await</span> insertRecord(<span class="hljs-string">"users"</span>, user);
            res.status(<span class="hljs-number">200</span>).json(<span class="hljs-string">"User created successfully"</span>);
        }
    } <span class="hljs-keyword">catch</span> (err) {
        res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">err</span>: err.message });
    }
};

<span class="hljs-built_in">module</span>.exports = { register };
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/SUccessValid-1.JPG" alt="Image" width="600" height="400" loading="lazy">
<em>API testing in Postman</em></p>
<p>Ensuring that the code followed our defined schema resulted in it being successfully executed.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. I hope you’ve learned about data validation, various data validation tools and data validation best practices.</p>
<p>You can also reach out to me and check out my other articles <a target="_blank" href="https://www.freecodecamp.org/news/author/oluwatobi/">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Migrate Your Local Data to MongoDB Atlas ]]>
                </title>
                <description>
                    <![CDATA[ Data forms the bedrock of our daily lives, as a lot of day-to-day decision-making is hinged on its existence. Just like energy, data can be transformed from one medium to another. So far, web development has become much more advanced, and data migrat... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mongodb-data-migration/</link>
                <guid isPermaLink="false">66bb58cc0da5b03e481107d8</guid>
                
                    <category>
                        <![CDATA[ Cloud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwatobi ]]>
                </dc:creator>
                <pubDate>Mon, 18 Mar 2024 14:40:31 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/mongoCloud.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Data forms the bedrock of our daily lives, as a lot of day-to-day decision-making is hinged on its existence. Just like energy, data can be transformed from one medium to another.</p>
<p>So far, web development has become much more advanced, and data migration and backup is an essential skill every web developer should have to help ensure continuity of data and preserve user information regardless of any circumstances.</p>
<p>For developers like me who prefer to test all their code features locally in a development environment before final deployment to the cloud, this tutorial would come in handy for you when faced with the challenge of migrating your locally stored MongoDB data to a cloud platform or any other platform.</p>
<p>The inspiration for this article is a result of the need for me to migrate the total JSON data on my local MongoDB Compass server to the cloud (MongoDB Atlas) for an ongoing project. I waded through the endless internet resources and documentation but couldn’t get a suitable, straightforward fix. With multiple trials and errors, I was able to succeed with the migration. This article should serve as the definitive guide you need to save you time and achieve fast results.</p>
<p>In this article, we'll delve into data management in MongoDB, data backup, and efficient data migration tools that ease up the entire process. This article is suited for people with intermediate to advanced knowledge of MongoDB and backend development. </p>
<p>If you have any difficulty with the terminologies used in this article, I would suggest studying the MongoDB documentation <a target="_blank" href="https://www.mongodb.com/docs/">here</a>. </p>
<p>Let’s begin.</p>
<h2 id="heading-introduction-to-mongodb">Introduction to MongoDB</h2>
<p>MongoDB is a non-relational NoSQL-based database that stores data via the document model in a JSON format. It’s quite popular, and ranks top among the most used databases worldwide.</p>
<p>It's also more code-friendly as it's currently the default database used by many JavaScript-based full stack and backend developers.</p>
<p>It has various database options, comprising both local database servers and a cloud-based Database-As-A-Platform. </p>
<p>A good example of this is the MongoDB Atlas. MongoDB Atlas is a flexible and scalable MongoDB implementation with strong cloud security.</p>
<p>It provides indexing, load balancing, and sharding, among other features. More information regarding it can be found <a target="_blank" href="https://www.mongodb.com/features">here</a>.</p>
<h2 id="heading-how-to-initialize-the-mongodb-server">How to Initialize the MongoDB Server</h2>
<p>You should have the MongoDB local server already installed. However, if you haven’t installed it, it can be downloaded <a target="_blank" href="https://www.mongodb.com/try/download/community">here</a>.</p>
<p>The MongoDB server can then be easily executable by adding its path to the environmental variables on Windows.</p>
<p>To initialize the MongoDB application, activate the command prompt and type in<br><code>Mongod</code></p>
<p><img src="https://hackmd.io/_uploads/r1aAf6gCp.jpg" alt="Mongo DB server running" width="600" height="400" loading="lazy">
<em>MongoDb server running</em></p>
<p>To explore the databases on the MongoDB server, open the MongoDB command shell and type <code>show dbs</code>  </p>
<p><img src="https://hackmd.io/_uploads/rJY2G6eC6.jpg" alt="The databases in my mongodb server" width="600" height="400" loading="lazy">
<em>The databses on the MongoDB server</em></p>
<p>This displays all the databases on the MongoDB server.</p>
<p>With this, let's go on to migrate one of these databases to the cloud.</p>
<h2 id="heading-how-to-back-up-data">How to Back Up Data</h2>
<p>To efficiently upload the database collections to the cloud, they must first be backed up.</p>
<p>To back up your database, you'll have to install an additional tool. Navigate back to the MongoDB downloads site and download the MongoDB database administration <a target="_blank" href="https://www.mongodb.com/try/download/database-tools">tools</a>.</p>
<p>This package contains a lot of database tools, such as <code>MongoExport</code>, <code>MongoImport</code>, <code>MongoDump</code>, and <code>MongoRestore</code>. </p>
<p>The above settings are applicable for users who have a version of MongoDB above version 4.4. MongoDB decided to release it as a stand-alone tool. For users whose version is less than version 4.4, these tools can be pre-installed in the MongoDB package.</p>
<p>Now, let's go on to the two major tools that would help facilitate the migration process: <code>MongoDump</code> and <code>MongoRestore</code>.</p>
<p>When <code>MongoDump</code> is executed on a database, it helps to create a backup database file in a binary-encoded JSON format (BSON). While the <code>MongoRestore</code> helps to return the backed-up database to MongoDB for usage.</p>
<p>Moving on, ensure that their package path is included in the environmental variables so as to guarantee efficient execution.</p>
<p>In order to back up a local database, open the MongoDB shell and then enter this command:</p>
<pre><code>Mongodump --db={TheNameOFYourDB} --collection={TheNameOfYourCollection} –out={The name <span class="hljs-keyword">of</span> the folder the backed up <span class="hljs-built_in">JSON</span> files would be located}
</code></pre><p>With this execution, you have successfully backed up your local MongoDB database.</p>
<h2 id="heading-how-to-set-up-a-mongodb-atlas">How to Set Up a MongoDB Atlas</h2>
<p>MongoDB Atlas is MongoDB cloud Database-As-A-Service cloud option accessible to its users at all times with little to no disruption.</p>
<p>Also, for most production apps that utilize the power of MongoDB on the server as a database tool, the easiest and most convenient provider of this solution is the MongoDB Atlas.</p>
<p>Hence, it is our choice to back up our MongoDB data to the cloud. I would assume you already have a MongoDB Atlas account, but you can still create one and then create a database that would serve as the recipient of the local database.</p>
<p>To set the account up, kindly navigate to the Atlas home page <a target="_blank" href="https://www.mongodb.com/atlas/database">here</a>. Create an account and you'll be directed to a dashboard where you can create new databases.  </p>
<p><img src="https://hackmd.io/_uploads/S15QNeGAp.jpg" alt="atllas" width="600" height="400" loading="lazy">
<em>MongoDb Atlas home page</em></p>
<p>You can, however, name it with any name you want. To complete the upload of the local MongoDB data to the cloud, navigate to the settings tab on the MongoDB Atlas database and click on the migrate data option. With this successfully done, let's now go on to complete the migration process.</p>
<h2 id="heading-how-to-migrate-your-data-to-the-cloud">How to Migrate Your Data to the Cloud</h2>
<p>To migrate your backed-up database to the cloud, <code>MongoImport</code> and <code>MongoExport</code> will be invoked.</p>
<p>In the command prompt, paste the migration code copied from the Atlas, and then execute it on the command prompt. With that, you should see a success text.</p>
<p>You can then check and refresh your cloud database to see the new files that have been uploaded there. Thereafter, you can connect the new cloud database to your backend application and run it successfully to get the same results on your local computer.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With this, we have come to the end of the tutorial. We hope you’ve learned about data management and migration in MongoDB, tools involved and all its intricacies. </p>
<p>Feel free to drop comments and questions, and also check out my other articles <a target="_blank" href="https://www.freecodecamp.org/news/author/oluwatobi/">here</a>. Till next time, keep on coding!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
