<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Poorshad Shaddel</title>
    <description>The latest articles on Forem by Poorshad Shaddel (@pshaddel).</description>
    <link>https://forem.com/pshaddel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F417963%2Fd3ac9ae5-9ada-47ed-aa28-cef96e6f8f1a.png</url>
      <title>Forem: Poorshad Shaddel</title>
      <link>https://forem.com/pshaddel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pshaddel"/>
    <language>en</language>
    <item>
      <title>Why Implementing Your Own Username Password Authentication System Could Be a Big Mistake!</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Tue, 26 Dec 2023 16:17:29 +0000</pubDate>
      <link>https://forem.com/pshaddel/why-implementing-your-own-username-password-authentication-system-could-be-a-big-mistake-2171</link>
      <guid>https://forem.com/pshaddel/why-implementing-your-own-username-password-authentication-system-could-be-a-big-mistake-2171</guid>
      <description>&lt;p&gt;This is an awareness about the dangers of implementing your authentication system!&lt;/p&gt;

&lt;h4&gt;
  
  
  Why I wrote this article?
&lt;/h4&gt;

&lt;p&gt;In almost all the projects and companies that I have worked with, we had our own &lt;strong&gt;Username Password&lt;/strong&gt; authentication system, as a result, we have faced a lot of challenges and this article is a summary of the challenges we had and what to consider before jumping into it.&lt;/p&gt;

&lt;p&gt;Some of the reasons I think using our own Username-Password authentication could be a mistake:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://cybernews.com/best-password-managers/most-common-passwords/" rel="noopener noreferrer"&gt;Cybernews&lt;/a&gt; analyzed 15 billion passwords and found that nearly 30 percent of them featured just &lt;strong&gt;8 characters&lt;/strong&gt; , 20 percent had just &lt;strong&gt;6 characters&lt;/strong&gt;!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“123456”&lt;/strong&gt; is still the most popular password (NordPass)&lt;/li&gt;
&lt;li&gt;Nearly &lt;strong&gt;6&lt;/strong&gt; in 10 Americans have used personal information such as their name or birth date in passwords (Google)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;52%&lt;/strong&gt; of internet users admit to resetting passwords regularly (ExpressVPN)&lt;/li&gt;
&lt;li&gt;Weak passwords are the root cause of &lt;strong&gt;81%&lt;/strong&gt; of all data breaches (Verizon)&lt;/li&gt;
&lt;li&gt;Just &lt;strong&gt;45%&lt;/strong&gt; of US consumers change their passwords after a data breach (Google)&lt;/li&gt;
&lt;li&gt;Hackers leaked over &lt;strong&gt;721 million&lt;/strong&gt; passwords in 2022&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another super important factor in my opinion is the &lt;strong&gt;massive amount of time that we need for implementing a good quality authentication system&lt;/strong&gt;. An authentication System is not something that you can deliver without a high test coverage, and that needs a lot of effort. In the next section we will see which features are needed for a authentication system and what to consider in implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqnhpun16zkmzj81m5os7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqnhpun16zkmzj81m5os7.png" alt="Picture of a Login page and a man and woman beside it" width="800" height="778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication Features and Challenges
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Choosing a Hash Function
&lt;/h4&gt;

&lt;p&gt;Some of the hash functions are considered weak, this is a small list:&lt;br&gt;&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/MD5" rel="noopener noreferrer"&gt;&lt;strong&gt;MD5&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/SHA-1" rel="noopener noreferrer"&gt;&lt;strong&gt;SHA-1&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/RIPEMD" rel="noopener noreferrer"&gt;&lt;strong&gt;RIPEMD&lt;/strong&gt;&lt;/a&gt; &amp;amp; &lt;strong&gt;RIPEMD-128&lt;/strong&gt; , &lt;a href="https://en.wikipedia.org/wiki/Whirlpool_(hash_function)" rel="noopener noreferrer"&gt;&lt;strong&gt;Whirlpool&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But probably this is not a big issue, since there are some other strong hash algorithms like &lt;a href="https://de.wikipedia.org/wiki/Argon2" rel="noopener noreferrer"&gt;Argon2id&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Bcrypt" rel="noopener noreferrer"&gt;bcrypt&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Scrypt" rel="noopener noreferrer"&gt;scrypt&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Secure Storing of Secret
&lt;/h4&gt;

&lt;p&gt;For hashing the password you probably need a secret. Keeping this secret secure is also really important. To avoid having this secret in your code, if you are using Kubernetes, you can use &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;K8s Secrets&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJA5S247VotYke8XHNj17eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AJA5S247VotYke8XHNj17eg.png" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Login with Email
&lt;/h4&gt;

&lt;p&gt;If you want to allow users to Login with their email, you already need a new implementation for verification of email. You already need a mail service even before starting your project! This verification could be done by sending a code, or a link that results in verification and a valid user session. Testing this is doable by mocking the mail service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APeSk0OOs4sIune5GwX-POw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APeSk0OOs4sIune5GwX-POw.png" alt="Login with Email" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Duplicated Emails
&lt;/h4&gt;

&lt;p&gt;It is easy to implement but the problem is that you are giving the anonymous request sender some information about existing users emails! So as a result you have to &lt;em&gt;use something like a rate limiter to avoid someone making a list of your application user emails by brute force&lt;/em&gt;.(preventing username or email enumeration attack)&lt;/p&gt;

&lt;h4&gt;
  
  
  Login or Register with Phone
&lt;/h4&gt;

&lt;p&gt;You need an SMS service to verify that the user owns the number. If you are allowing register with a phone number, also here you should be careful about Enumeration attacks, the attacker can get some existing phone numbers and try to target those users with social engineering or phishing attacks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARzh8Zq-sQ2ozLmRWBJQMWg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARzh8Zq-sQ2ozLmRWBJQMWg.png" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Password Policy
&lt;/h4&gt;

&lt;p&gt;Choosing the standard password policy is also important, For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not less than 8 Characters&lt;/li&gt;
&lt;li&gt;Up to 64 Characters&lt;/li&gt;
&lt;li&gt;Allow usage of &lt;strong&gt;all&lt;/strong&gt; characters including unicode and whitespace. There should be no password composition rules limiting the type of characters permitted.&lt;/li&gt;
&lt;li&gt;Include a &lt;em&gt;password strength meter&lt;/em&gt; to show the user how strong is their password!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/zxcvbn-ts/zxcvbn" rel="noopener noreferrer"&gt;zxcvbn-ts&lt;/a&gt; is a nice package for showing the strength of the password to the user.&lt;/p&gt;

&lt;p&gt;This is the most basic functionality of an Authentication System. the User should be able to log in with a username or password!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMPwNgBGS7_mj5DtQ-MpGVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMPwNgBGS7_mj5DtQ-MpGVQ.png" alt="Enter the Password" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Reset Password
&lt;/h4&gt;

&lt;p&gt;We usually send a reset password link or a code to allow the reset password process. What to consider?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sending consistent message(not email not found!)&lt;/li&gt;
&lt;li&gt;Response time in cases that the email does not exist!&lt;/li&gt;
&lt;li&gt;Tokens should be safe, single use and expriable!&lt;/li&gt;
&lt;li&gt;Use a Rate Limiter for avoiding Bruteforce&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ak_Tm_tTg3XWN4sZ6ktYpOA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ak_Tm_tTg3XWN4sZ6ktYpOA.png" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Locking Account on Multiple Try
&lt;/h4&gt;

&lt;p&gt;This is a logic quite similar to cell phones, if you enter the wrong pin a few times, you have to wait for a while to be able to try it again. In order to avoid brute force on specific accounts, you have to lock the account when someone is sending a lot of wrong passwords to that specific user. Implementing this logic requires also a policy for unlocking the account. For some use cases, they unlock the user after a period of time. For some other use cases only support users are able to unlock these users.&lt;/p&gt;

&lt;h4&gt;
  
  
  Session Management
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyyKrf_O27PaQOa8MeDBVGg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AyyKrf_O27PaQOa8MeDBVGg.png" alt="Google Showing List of Your Active Sessions" width="800" height="302"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Google Showing List of Your Active Sessions&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Session manager might also be something specific to Finance sector, but I had to implement it twice! But honestly this is not a complicated feature to implement, it just adds a bit of complexity and a bunch of code and more tests to your codebase.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Risk-Based Authentication (RBA)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;You see an email once in a while, when you try to Login from a new Browser or device in your Google Account. This restriction might be neccessary if you are working in finance sector. You need tell the user that there was a suspicious activity. Another result of this feature is that you need to store IP Address(or a Hash of it) somewhere to check each Login against this list of IP Addresses.&lt;/p&gt;

&lt;h4&gt;
  
  
  Persisting Sessions
&lt;/h4&gt;

&lt;p&gt;This is also a question that you should answer usually the moment you want to implement your own authentication system. Nowdays everyone is using containers and deploy their applications on K8s or Serverless, as a result you do not have a monolith and you might have more than once instance of the application, so you cannot use memory as a store for your sessions. Usually it is recommend to use a key-value store, because Databases are slow(I doubt this one! Databases are not slow specially if you have the correct index, they might not be as fast as key-value stores but they are definitely not slow!). So you need something like &lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5VQqsIfxoVVv4tY19CaGHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5VQqsIfxoVVv4tY19CaGHg.png" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Concerns
&lt;/h3&gt;

&lt;p&gt;These are only some of the security concerns and attacks which you should be familir with before thinking about your own authentication system.&lt;/p&gt;

&lt;h4&gt;
  
  
  BruteForce Attacks
&lt;/h4&gt;

&lt;p&gt;For fighting bruteforce attacks, having a complex rate limiter is vital. The user should not try a lot of username at registration, otherwise it can make a list of users and later target this group. User should not be able to send a lot of password reset emails at once. My favorite package on Nodejs is this &lt;a href="https://github.com/animir/node-rate-limiter-flexible" rel="noopener noreferrer"&gt;node-rate-limiter-flexible&lt;/a&gt; that supports complicated cases.&lt;/p&gt;

&lt;p&gt;If you are intereseted in checking out the details of BruteForce Attack you can check this article from me:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/pshaddel/prevent-brute-force-attacks-in-nodejs-36k2"&gt;Prevent Brute Force Attacks in Node.JS&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Username Enumeration
&lt;/h4&gt;

&lt;p&gt;The username enumeration is an activity in which an attacker tries to &lt;em&gt;retrieve valid usernames from a web application&lt;/em&gt;. The web applications are mostly vulnerable to this type of attack on &lt;strong&gt;login&lt;/strong&gt; pages, &lt;strong&gt;registration&lt;/strong&gt; form pages or password &lt;strong&gt;reset&lt;/strong&gt;  pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  SQL/NoSQL Injection
&lt;/h4&gt;

&lt;p&gt;You always have to validate data that comes from the user and frontend. Sanitizing is also vital in case of Login, Register and Reset Password. Sanitzing means that you are not letting the user to pass something like a regex that could do something you do not expect in your code(for example fetching all users instead of one).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/treyhuffine/how-to-prevent-no-sql-injection-in-nodejs-49n5-temp-slug-5562605"&gt;How to Prevent No-SQL Injection in Node.js&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  CSRF Attack
&lt;/h4&gt;

&lt;p&gt;Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. For example the attacker could execute change email, change password. Usually we solve this issue by using a CSRF Token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/treyhuffine/prevent-csrf-attacks-in-node-js-application-358b-temp-slug-3843041"&gt;Prevent CSRF Attacks in Node.JS application&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Session Fixation
&lt;/h4&gt;

&lt;p&gt;The attacker has his own valid session and tries to associate it with another user. The problems occur when we are not generating new sessionIds(unique identifier) on actions like Login. &lt;a href="https://github.com/jaredhanson/passport" rel="noopener noreferrer"&gt;Passportjs&lt;/a&gt; the most famous authentication library in nodejs had this vulneribility until version 0.5.0. Read the Passportjs maintainer article &lt;a href="https://medium.com/passportjs/fixing-session-fixation-b2b68619c51d" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have also covered this issue on my medium&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/pshaddel/what-is-session-fixation-and-how-to-prevent-it-in-nodejs-3lnn-temp-slug-5112535"&gt;What is Session Fixation and How to Prevent it in Node.js&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  More Code, More Bugs!
&lt;/h3&gt;

&lt;p&gt;I think this is not 100% true, the more accurate sentence will be “The More Code, The More Possibility of Bugs”. If we implement all of these logics in our code, even if we are aware of security concerns there is a good posibility that we see some bugs, in both category of security, and functionality. This is another reason why I wrote this article, all these logic could be handled by somthing like Google, Apple, Github or any third party authentication service and we can focus on our business logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://softwareengineering.stackexchange.com/questions/41949/more-code-more-bugs" rel="noopener noreferrer"&gt;More code = more bugs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Is there a Solution?
&lt;/h3&gt;

&lt;p&gt;Definitely!, you can use &lt;a href="https://www.passportjs.org/concepts/authentication/google/" rel="noopener noreferrer"&gt;Google Login&lt;/a&gt;, &lt;a href="https://www.passportjs.org/packages/passport-apple/" rel="noopener noreferrer"&gt;Apple Login&lt;/a&gt;, &lt;a href="https://www.passportjs.org/packages/passport-github/" rel="noopener noreferrer"&gt;Github Login&lt;/a&gt; or Third Party Authentication Services like &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keycloak&lt;/a&gt;, &lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;, &lt;a href="https://aws.amazon.com/pm/cognito/" rel="noopener noreferrer"&gt;AWS Cognito&lt;/a&gt;, &lt;a href="https://fusionauth.io/" rel="noopener noreferrer"&gt;FusionAuth&lt;/a&gt; and a lot of other options(both open source and closed source). By not implementing authentication yourself you are saving a lot of time and energy. My personal experience was that we could not ignore a good test coverage for authentication features and bugs, as a result we had to implement a lot of tests to be sure that everything is working as expected.&lt;/p&gt;

&lt;h4&gt;
  
  
  What if we loose some users because of not having the traditional username password?
&lt;/h4&gt;

&lt;p&gt;This is a question that only your specific product and targeted users can correctly answer, but it is always a trade off, you might loose some users but you gain time and energy for building more business related features that might attract some more users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Implementing our own authentication system could be a big security risk, and even for those who do not care that much about security(Do you really?), the cost of implementing all the features, tests and manual testing is really high. I think this is a mistake beacuse there are a lot of easier options which their main focus is this topic and the possiblity that they make mistakes is much less than us!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html" rel="noopener noreferrer"&gt;Authentication - OWASP Cheat Sheet Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://passkwall.medium.com/timing-based-username-enumeration-whats-a-fix-versus-mitigation-8a0f8c7191f2" rel="noopener noreferrer"&gt;Timing-Based Username Enumeration: What’s a fix versus mitigation?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.xperience.io/spaces/flyingpdf/pdfpageexport.action?pageId=62069615#:~:text=File%20enumeration-,Username%20enumeration,pages%20or%20password%20reset%20pages" rel="noopener noreferrer"&gt;https://docs.xperience.io/spaces/flyingpdf/pdfpageexport.action?pageId=62069615&lt;/a&gt;&lt;/p&gt;




</description>
      <category>username</category>
      <category>authentication</category>
      <category>security</category>
      <category>sso</category>
    </item>
    <item>
      <title>What is Session Fixation and How to Prevent it in Node.js</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Mon, 13 Nov 2023 00:18:18 +0000</pubDate>
      <link>https://forem.com/pshaddel/what-is-session-fixation-and-how-to-prevent-it-in-nodejs-5c7c</link>
      <guid>https://forem.com/pshaddel/what-is-session-fixation-and-how-to-prevent-it-in-nodejs-5c7c</guid>
      <description>&lt;p&gt;By Session Fixation attacker can hijack a valid user session and it is absolutely important to know this vulnerability and protection against it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4vz3mma9z41v38xabqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4vz3mma9z41v38xabqi.png" width="800" height="498"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Session Fixation and How to Fix it&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before diving into this we need to know what, the session is and how session authentication works. If you are already familiar with this you can skip to the part: &lt;em&gt;What is Session Fixation&lt;/em&gt; or &lt;em&gt;How to Prevent Session Fixation&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Session?
&lt;/h3&gt;

&lt;p&gt;As we know HTTP requests are stateless, it means that when we send my Login request, and we have a valid username and password there is not a default mechanism to know that I am the same person who is sending the next request. For solving this and in other words make the requests stateful there are some suggested ways like &lt;strong&gt;Cookies&lt;/strong&gt; , &lt;strong&gt;Hidden Form Fields&lt;/strong&gt; , &lt;strong&gt;URL Parameters&lt;/strong&gt; , &lt;strong&gt;HTML5 Web Storage&lt;/strong&gt; , &lt;strong&gt;JWT and Session&lt;/strong&gt;. In this article we are focusing on Session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session&lt;/strong&gt; is a data stored on the server. Each client is given a &lt;strong&gt;unique identifier&lt;/strong&gt; &lt;em&gt;associated with this data on the server&lt;/em&gt;. The client must send this unique identifier on each request, so we know who is sending this request. This identifier could be sent in a cookie or URL parameter.&lt;/p&gt;

&lt;p&gt;A simplified example to show the session and identifier (sessionId) in an &lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;expressjs&lt;/a&gt; application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const app = require('express')();
const session = require('express-session');
app.use(require('cookie-parser')());
app.use(require('body-parser').json());

app.use(session({
    secret: 'secret',
    cookie: { maxAge: 60000 },
    name: 'sessionId'
}));

app.get('/', (req, res) =&amp;gt; {
    res.send('ping');
});

app.listen(3000, () =&amp;gt; {
    console.log('Server is running on port 3000');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When sending a request for the first time the express-session middleware is &lt;strong&gt;creating a new unique identifier and sets it as a cookie and stores this somewhere (in this case memory, but we can pass our custom store too)&lt;/strong&gt;. In the options of session middleware, we have used sessionId as the name of our key that stores this unique identifier. Now if we send a request, we see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHmuxUX1FEexkGKEem-CIFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AHmuxUX1FEexkGKEem-CIFQ.png" alt="Session Middleware Assinging a new Session Id" width="800" height="150"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Session Middleware setting a new Session Id&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Browsers now set this cookie and store it automatically for further requests. If we send a request that contains a valid session (the session exists in our session store - memory in our case) we do not get the Set-Cookie header in the response back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AzPlfI1r5MnD0SO-N1Tf5Ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AzPlfI1r5MnD0SO-N1Tf5Ng.png" width="800" height="150"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;No Set-Cookie When we have a valid session.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When the user signs in we can store the user information in the cookie(serialized) or we can store it in a database and associate the data with the sessionId. Let’s use a Map as our database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const db = new Map();
app.get('/me', (req, res) =&amp;gt; {
    const user = db.get(req.sessionID);
    res.json({ mySessionId: req.sessionID, me: user ? user : 'anonymous' });
});
const users = [{ name: 'bob', age: 19 }, { name: 'joe', age: 20 }];
app.post('/login', (req, res) =&amp;gt; {
    const { name } = req.body;
    const user = users.find(u =&amp;gt; u.name === name);
    if (user) {
        db.set(req.sessionID, user);
        res.send('ok');
    } else {
        res.send('try again');
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we login and then use the cookie to send another request to /me we get this result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AS-XYc590UneZisgd5jdi0Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AS-XYc590UneZisgd5jdi0Q.png" width="800" height="156"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;User Data associated with Session Id&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was a simplified summary of why we have to use session and how we can do that.&lt;/p&gt;
&lt;h4&gt;
  
  
  Can an Attacker Create a Valid Session Id?
&lt;/h4&gt;

&lt;p&gt;In this case that we were using express-session . you saw that we passed a secret to session middleware. This secret is used for signing the value of our cookie. It simply means that we are sure that it was us who generated the sessionId. So as long as you are sending signed values to your clients, it is not possible.&lt;/p&gt;

&lt;p&gt;A sample of session:&lt;br&gt;&lt;br&gt;
sessionId=s%3AL6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP.x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs&lt;/p&gt;

&lt;p&gt;First Part: s%3A simply means: s: which is a prefix to indicate that our cookie-session is signed!&lt;/p&gt;

&lt;p&gt;Second Part: L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP this is our sessionId, we are using this in our database for associating data.&lt;/p&gt;

&lt;p&gt;Third Part: This is the third part: x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs This is the signing part. We have generated this text by using our secret, so we can be sure that this cookie is generated by us.&lt;/p&gt;

&lt;p&gt;We can simply regenerate this sign and check if it is valid or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const crypto = require('crypto');
const secret = 'secret';
const sessionId = 'L6j4T8hBwMk1ulJqGoisZbAxUOkOuQqP';
const hmac = crypto.createHmac('sha256', secret);
hmac.update(sessionId);
const signature = hmac.digest('base64').replace(/\=+$/, '');
console.log(signature); // x5UxPQEtKrj3sWrIy6S01CQRjAtp4biVs4H2zgqmSs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how express-session is checking it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Session Fixation?
&lt;/h3&gt;

&lt;p&gt;In Session Fixation attacks, the attacker hijacks a valid user session. We said that we sign the cookie in order to be sure that no one can hijack another user's valid session. But what if the attacker has his own valid session and tries to associate it with another user? in this case he can perform actions on behalf of the victim.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problems occur when we are not generating new sessionIds(unique identifier) on actions like Login&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  How can the Attacker do this?
&lt;/h4&gt;

&lt;p&gt;One of the cases is when attacker has physical access to the computer. As an attacker, I go to the university and I choose one of the shared computers, then I sign into my account on the vulnerablewebsite.com and then without doing the logout (which normally destroys the session in the server store), I leave an open login page on vulnerablewebsite.com and before that I have to copy my valid sessionId. Now the victim is using this computer and if the victim signs in, the attacker sessionId is associated with the victim's account. Sounds complicated? Not at all, let’s see that in action:&lt;/p&gt;

&lt;p&gt;Let’s login with our first user Bob(Attacker):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABsCrVaYRUxQYZI1s0YDd2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABsCrVaYRUxQYZI1s0YDd2g.png" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the browser sets this cookie for this website. It means if someone else tries to send the login request, express-session is not generating a new sessionId and what it does &lt;strong&gt;&lt;em&gt;is overriding the existing&lt;/em&gt;&lt;/strong&gt; sessionId.&lt;/p&gt;

&lt;p&gt;Let’s imagine &lt;strong&gt;Joe&lt;/strong&gt; (victim) decides to use this shared computer, &lt;strong&gt;the cookie and the valid session of Bob&lt;/strong&gt; is also sent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AdqtMTDwj4PQ_-VKdA30oWw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AdqtMTDwj4PQ_-VKdA30oWw.png" width="800" height="268"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Login with sending an existing valid session&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We did not get a new session or cookie!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The magic happened and now the sessionId of Bob is associated with Joe’s user. So, if the attacker (Bob) sends a request to /me he will get data of Joe back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUnbJWeWd4zwxDePngP2Ebw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUnbJWeWd4zwxDePngP2Ebw.png" width="800" height="271"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Using Bob Session Id for getting Joe Data&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We were able to get Joe Data by using the Session of Bob. In this example the attacker had physical access, but it is possible to do it without physical access if there are some other vulnerabilities such as XSS.&lt;/p&gt;

&lt;p&gt;Some websites are passing sessionId as URL parameters in requests. In this case if the attacker gives a link to login page with his sessionId on URL parameters there is a possibility to exploit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AC7PBNl1tAw9nh8N9QTipJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AC7PBNl1tAw9nh8N9QTipJg.png" width="800" height="307"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Session Fixation by URL Parameter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Read more about security challenges of this method in &lt;a href="https://security.stackexchange.com/questions/14093/why-is-passing-the-session-id-as-url-parameter-insecure" rel="noopener noreferrer"&gt;this stack exchange question&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Prevent Session Fixation?
&lt;/h3&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Generate New Sessions on Login!&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The main solution is really easy, by doing that you are always sure that this session override is not happening!&lt;/p&gt;

&lt;p&gt;Let’s change our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post('/login', (req, res) =&amp;gt; {
    const { name } = req.body;
    req.session.regenerate(err =&amp;gt; {
        if (err) {
            res.send('error');
        } else {
            const user = users.find(u =&amp;gt; u.name === name);
            if (user) {
                db.set(req.sessionID, user);
                res.send('ok');
            } else {
                res.send('try again');
            }
        }
    });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use regenerate function, in order to assign a new session each time someone wants to log in. It does not matter anymore if you pass a session cookie or not, it will generate a new session Id and sends it to the client in the Set-Cookie Header.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7Bz_0mrEnnpWnBSy-Lj6Qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7Bz_0mrEnnpWnBSy-Lj6Qw.png" width="800" height="307"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each Time We Log in we get a new sessionId and Set-Cookie Header&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Only Use HTTP Only Cookies
&lt;/h4&gt;

&lt;p&gt;When you are using HTTP Only, it means that only server can set cookies by Set-Cookie header and the client side (Browser JavaScript) cannot change it. So even if your app has a XSS vulnerability, the attacker cannot change sessionId (cookie).&lt;/p&gt;

&lt;h4&gt;
  
  
  Protect against XSS
&lt;/h4&gt;

&lt;p&gt;Session Fixation can be combined with XSS attacks to be more effective, so it does make sense to take XSS attacks also serious if you are concerned about session fixation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Sensible Session Expiration Time
&lt;/h4&gt;

&lt;p&gt;The sessions expiration should match your application specific requirements, if you are more concerned about security then it should be shorter and vice versa.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Correct Logout Implementation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;On Logout you have to correctly destroy the existing session and its association with any data. Otherwise, these sessions could be used after logout. (It is not enough to remove the cookie from client browser!)&lt;/p&gt;

&lt;h3&gt;
  
  
  Was Passportjs Vulnerable to Session Fixation?
&lt;/h3&gt;

&lt;p&gt;Yes, in versions before 0.6.0 the issue was there, Passport maintainers thought that session regeneration should be done on the application side, but after a while they realized the importance of the issue and they fixed it in 0.6.0 version. If you are interested in the details of this fix, you can read all the details &lt;a href="https://medium.com/passportjs/fixing-session-fixation-b2b68619c51d" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Session fixation could occur in case of overriding an existing sessionId with another user data. The solution is quite straight forward by generating a new session each time someone signs in, using HTTP Only cookies, proper expiration time, correct logout implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://owasp.org/www-community/attacks/Session_fixation#" rel="noopener noreferrer"&gt;https://owasp.org/www-community/attacks/Session_fixation#&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#session_fixation" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Security/Types_of_attacks#session_fixation&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#renew-the-session-id-after-any-privilege-level-change" rel="noopener noreferrer"&gt;Session Management - OWASP Cheat Sheet Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hacksplaining.com/prevention/session-fixation" rel="noopener noreferrer"&gt;Protecting Your Users Against Session Fixation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>security</category>
      <category>sessions</category>
      <category>node</category>
      <category>sessionfixation</category>
    </item>
    <item>
      <title>Implement a Simple Version Control with JavaScript to Understand Git Better!</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Sun, 29 Oct 2023 21:35:16 +0000</pubDate>
      <link>https://forem.com/pshaddel/implement-a-simple-version-control-with-javascript-to-understand-git-better-48i6</link>
      <guid>https://forem.com/pshaddel/implement-a-simple-version-control-with-javascript-to-understand-git-better-48i6</guid>
      <description>&lt;p&gt;Learn Git Internals by trying to implement a simplified version of it!&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Git or generally Version Control?
&lt;/h3&gt;

&lt;p&gt;Simply something that helps us track our project over time. One good example is that we can easily go back in time in our source code and see how the code looked like at a specific time in the past.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we need to understand it?
&lt;/h3&gt;

&lt;p&gt;First of all, because when something goes wrong just blindly knowing some commands will not help. Second of all, if we do not understand how the thing, we are working with it every day is working, then where is the fun?&lt;/p&gt;

&lt;p&gt;Now we will understand the concepts one by one in the way of implementing our super simplified version control called Gitj&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Keep in mind that git does so many more advanced things like compression and the way thing are stored that I might cover in separate articles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement the first command: Init!
&lt;/h3&gt;

&lt;p&gt;As you probably know we start the project by git init and git creates the .git folder and stores data in it. We are going to implement this:&lt;/p&gt;

&lt;p&gt;Two important folders that git creates are refs and objects. Objects are building blocks of git, they can have 3 types(actually 4!): commit , tree and blob . We are going to see each one of these types in details. refs folder has a subfolder called heads that contains our branches and the latest commit of each branch(from the name it should be kind of obvious that it stores the head of the branch). We have also an important file called HEAD which keeps the current branch or commit.(sometimes we want to checkout on a commit and not a branch)&lt;/p&gt;

&lt;p&gt;So let’s create these folders when someone is calling our init function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// creates a folder called .gitj and creates a subfolder called .gitj/objects and .gitj/refs and .gitj/refs/heads&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/objects&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/refs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/refs/heads&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// creates a file called .gitj/refs/heads/master&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/refs/heads/master&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// creates a file called .gitj/HEAD&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/HEAD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ref: refs/heads/master&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Git Add! Put files into Staging
&lt;/h3&gt;

&lt;p&gt;In git files can have three different stages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsy073o6rj8eh39d38pl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsy073o6rj8eh39d38pl.png" width="800" height="465"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Git Files Stages&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Working Directory&lt;/strong&gt; : your normal directory that you work on it and you change files and folders and structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staging Directory:&lt;/strong&gt; This is a snapshot of a moment in your working directory and when you use git add command it is actually copies your files to .git folder. Keep in mind that staging files are somehow final draft that you want to later commit to your repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository&lt;/strong&gt; : By running commit command you are creating a new snapshot in your repository. Now you can point to this snapshot by using the SHA Hash of this commit(you could not point to staging files, staging files were kind of draft).&lt;/p&gt;

&lt;p&gt;Now let’s implement git add command.&lt;/p&gt;

&lt;p&gt;The steps we should do in git add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Read the file content&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Hash the content of the file&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Use Hash as file name and store it in the objects folder&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;If the file is already there, do nothing. If you have 10 files with identical contents (even with different file name and folder location) git does not copy them 10 times, it can re-use the blob.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, git uses first two letters of hash and creates a folder name. For example, if the hash is 4f9be057f0ea5d2ba72fd2c810e8d7b9aa98b469 . git stores it in this folder: 4f and creates this file with the rest: 9be057f0ea5d2ba72fd2c810e8d7b9aa98b469 . The reason is that when over time there are a lot of files in a single folder accessing files could be slower and by using the first two letters as a folder git tries to prevent this problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// file exists?&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;accessSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// read the file&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// hash the file&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// create a folder with the first two characters of the hash if it doesn't exist&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gitj/objects/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// a blob with the same content already exists&lt;/span&gt;
            &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// write the file to the objects folder&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`File &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; does not exist.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sample/src/readme.md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running add.js and adding a file from your source code you should see a file in your objects repository like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq75yio0g12vq8wq4gar1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq75yio0g12vq8wq4gar1.png" width="800" height="156"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How your Gitj folder should look like&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Commit the Changes!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Commit&lt;/strong&gt; itself is also an object type and as you are probably guessing it should create more files in our objects folder.&lt;/p&gt;

&lt;p&gt;The intention of commit is to make a pointer to the current situation (files and folders) that we can point to and in the future, we can come back to this state.&lt;/p&gt;

&lt;p&gt;A commit object in Git contains this information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Author&lt;/em&gt;: The person who made the changes&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Committer&lt;/em&gt;: The person who commit the changes (sometimes you receive a patch from someone else and you have to commit changes.)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Date of commit&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Commit Message&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Tree&lt;/em&gt; (which is itself another object that keeps the shape of working directory at the time of creation)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Parent&lt;/em&gt;(If exists)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Let’s see how the Git Commit looks like
&lt;/h4&gt;

&lt;p&gt;If we use command git log we can see the list commit hashes and if we copy one of them, we can use the command git show --pretty=raw commitHash . Here is an example of result of this command(Date is represented as timestamp after the commiter and author name):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mlds43z2wtwqx7wn1db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mlds43z2wtwqx7wn1db.png" width="800" height="117"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Result of Git Show Commit&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example we have a parent but if the commit is the first commit ever, then we do not have a parent.&lt;/p&gt;

&lt;p&gt;The reason the parent exists inside commit object is that by doing that we can chain these commits together and if we manually change a commit in the past everything goes wrong because all the commit hashes should be recalculated. This is something that we do by using commands like rebase .&lt;/p&gt;
&lt;h4&gt;
  
  
  What is Tree object type in Git?
&lt;/h4&gt;

&lt;p&gt;It is a type of object that keeps the shape of folders and files. For exampe in the commit example that I showed, we can checkout the Tree object and see what is inside. For seeing the tree we have to use git ls-tree treeHash . Here is an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faukwh1rflvtgzpvdtxjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faukwh1rflvtgzpvdtxjo.png" width="800" height="141"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Git LS Tree Command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the base tree. It contains the files and folders of my working directory. As we can see it has two different types: blob which are files, and tree &lt;strong&gt;which points to another tree object that represents a sub folder in this case.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the result second column is the type of object, third one is the SHA and the last one is file or folder name(We already mentioned that keeping file name out of blob helps to reuse the exact same content over and over). The only thing we do not know yet is the first column. First column is &lt;strong&gt;File Mode.&lt;/strong&gt; The file mode specifies the type of the object (e.g., blob, tree) and its permissions. The leading numbers like 040000 or 100644 represent the file mode in octal notation. The most common modes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100644: Indicates a normal file (blob) with read-write permissions.&lt;/li&gt;
&lt;li&gt;100755: Indicates an executable file (blob) with read-write-execute permissions.&lt;/li&gt;
&lt;li&gt;040000: Indicates a directory (tree).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Actions needed to implement commit functionality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a Tree of the current working directory&lt;/li&gt;
&lt;li&gt;Create the commit object&lt;/li&gt;
&lt;li&gt;Get the parent commit(Head), if there is not parent update the head(master) after this commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are going to create a simple tree that generates the structure of files and folders in the same way that git does.&lt;/p&gt;
&lt;h4&gt;
  
  
  Implement Tree generator function!
&lt;/h4&gt;

&lt;p&gt;Small function for getting the &lt;em&gt;file mode&lt;/em&gt; of each file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTreeFileMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileOrFolder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileOrFolder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fileType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;040000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;777&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A function to get hash of a file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHashOfFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the main function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createTreeObjectsFromPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;treeFileContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
    &lt;span class="c1"&gt;// we want to create a tree object similar to git ls-tree&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listOfFilesAndFolders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;withFileTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// if it is a file we want to store the hash of the file, if it is a directory we want to call this function recursively&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileOrFolder&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;listOfFilesAndFolders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileOrFolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileOrFolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fileHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createTreeObjectsFromPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;fileHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// here we need to calculate the hash of the file&lt;/span&gt;
            &lt;span class="nx"&gt;fileHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getHashOfFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getTreeFileMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileModeAndName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileMode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;treeFileContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;fileModeAndName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;treeFileContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;treeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// write the tree object to the objects folder&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;folderOrFileExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;folderOrFileExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// a tree with the same content already exists&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// write the file to the objects folder&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;treeFileContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// console.log(`.gitj/objects/${treeHash.slice(0, 2)}/${treeHash.slice(2)} \n`, treeFileContent);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explaination of this function:&lt;/p&gt;

&lt;p&gt;1- We are iterating to result of fs.readdir .&lt;br&gt;&lt;br&gt;
2- If it is a directory then type is tree and we are calling this function recursively. Otherwise it is a file or blob in other words and we need to calculate the hash.&lt;br&gt;&lt;br&gt;
3- We get the file mode(040000, 100644, …) because we need it for creating our tree object.&lt;br&gt;&lt;br&gt;
4- We have the content of tree object. Now we can create the hash.&lt;br&gt;&lt;br&gt;
5- if the object(hash of current tree) exists we do not need to do anything otherwise we create the object and store it into our objects folder.&lt;/p&gt;

&lt;p&gt;Let’s run this function and see if it is working correctly:&lt;/p&gt;

&lt;p&gt;The folder structure look like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEQUub-GtcqIb4_6HUeE2gA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEQUub-GtcqIb4_6HUeE2gA.png" width="800" height="95"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Folder Strucutre&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we run createTreeObjectsFromPaths('.') . As a result two new objects are created in our Gitj folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F954%2F1%2ATjtLXzt-5ot_xiVAsbTYMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F954%2F1%2ATjtLXzt-5ot_xiVAsbTYMA.png" width="800" height="397"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two new objects after creating our tree object&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We expect the content of one of these objects to have package.json which was in the root folder as a type of blob and we expect another tree object which points to src folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AymGbFAYZEat0jGcV0w0Cmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AymGbFAYZEat0jGcV0w0Cmw.png" width="800" height="108"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Root Folder Tree Object&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This tree commit hash now refers to another object that stores structure of src folder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOdjd7S5RGn3kwfz888VvkQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOdjd7S5RGn3kwfz888VvkQ.png" width="800" height="93"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;src Folder Tree Object&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now it’s time to implement Commit function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createTreeObjectsFromPaths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;folderOrFileExist&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commitMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createTreeObjectsFromPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sample&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parentHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getLatestCommitHash&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;committer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commitDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commitContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`tree &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nparent &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;parentHash&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nauthor &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\ncommitter &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;committer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\ncommit date &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitDate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commitContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commitHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// write the commit object to the objects folder&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;folderOrFileExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;folderOrFileExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// a commit with the same content already exists&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// write the file to the objects folder&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commitContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// set the head of current branch to the commit hash&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.gitj/refs/heads/master&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hard part was the tree object, now we have all the data and we put them together and create a new object for commit. Also, we need to update the head of the branch and point to this new snapshot that we got (obviously the commit hash).&lt;/p&gt;

&lt;h3&gt;
  
  
  Git Checkout
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What does branch Master or Main or other branches mean?
&lt;/h4&gt;

&lt;p&gt;Branches are simply reference or bookmark to a commit. In the implementation of commit you saw that since we updated the content of file: refs/head/master , it is just a commit hash. And this commit hash has a parent(if it is not the first commit ever) and we can go back to history until there is no commit anymore. So, by using this branch name we can access the latest commit (Head!). Simply, being on a branch means that you are pointing to another head.&lt;/p&gt;

&lt;p&gt;it does not store the file name with the blob, then the advantage is that git can use the blob even if the file names are different.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to implement Git Checkout!
&lt;/h4&gt;

&lt;p&gt;Since we already implemented commit functionality, we know that in a commit we have access to tree object (recursively all the folders and files) and we have files as blob in the .git(for us .gitj). So we should remove the working directory and then build the whole directory when someone is checking out on another commit(or branch — branch head points to a commit hash). But first of all we need to store the commit hash or the branch name to the file HEAD .&lt;/p&gt;

&lt;p&gt;Before that we want to implement a small function to get the tree object of that commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTreeHashFromCommit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commitContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;commitContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now by having the tree we have to rebuild the whole folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listOfFilesToCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="c1"&gt;// store the commit hash in the refs folder&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.gitj/HEAD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;treeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getTreeHashFromCommit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commitHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// get tree file&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;convertTreeObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// clear the folder&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;removeAllFilesAndFolders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// create the files and folders based on address on the blob&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createFilesAndFolders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;folderPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First we are writing this commit to HEAD file to remember that the head is not on master anymore. We have to recursively get the tree and their blobs to re-create the whole folder. Here is the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;convertTreeObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;folderPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;treeObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`.gitj/objects/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;treeHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;treeObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tree&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;convertTreeObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;folderPrefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;folderPrefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we have a file then we add the name file and the blob( content of the file) to an array. if the object type is tree it means that it is a folder and we need to call this function recursively and we have to path the parent folder to create the correct path to the file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Some more functionalities that I would like to implement in future
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Git Status&lt;/li&gt;
&lt;li&gt;Git Diff&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We have learned how git uses hashes and chaining of commit hashes to give us the ability of tracking the history. Personally, I find this kind of deep dive the best way to learn something really good, I hope it was useful. If you are interested in implementing more functionalities in git checkout this &lt;a href="https://github.com/pshaddel/gitjs" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pshaddel/gitjs" rel="noopener noreferrer"&gt;GitHub - pshaddel/gitjs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/doc" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=lG90LZotrpo&amp;amp;ab_channel=CS50" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=lG90LZotrpo&amp;amp;ab_channel=CS50&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=P6jD966jzlk&amp;amp;pp=ygUgR2l0IGludGVybmFscyBob3cgaXQgc3RvcmVzIGRhdGE%3D" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=P6jD966jzlk&amp;amp;pp=ygUgR2l0IGludGVybmFscyBob3cgaXQgc3RvcmVzIGRhdGE%3D&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=dBSHLb1B8sw&amp;amp;ab_channel=GOTOConferences" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=dBSHLb1B8sw&amp;amp;ab_channel=GOTOConferences&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=52MFjdGH20o&amp;amp;ab_channel=Brief" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=52MFjdGH20o&amp;amp;ab_channel=Brief&lt;/a&gt;&lt;/p&gt;




</description>
      <category>javascript</category>
      <category>git</category>
      <category>versioncontrol</category>
    </item>
    <item>
      <title>Comparing Prisma and Mongoose for MongoDB: A Comprehensive Analysis</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Sun, 03 Sep 2023 15:54:29 +0000</pubDate>
      <link>https://forem.com/pshaddel/comparing-prisma-and-mongoose-for-mongodb-a-comprehensive-analysis-2lja</link>
      <guid>https://forem.com/pshaddel/comparing-prisma-and-mongoose-for-mongodb-a-comprehensive-analysis-2lja</guid>
      <description>&lt;p&gt;Mongoose is the most used ODM with MongoDB and Prisma is a modern ODM/ORM that supports MongoDB in this article we are going to do a complete comparison between these two in various areas!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kg4ogkzb921byy7h6s6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kg4ogkzb921byy7h6s6.png" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prisma vs Mongoose — Designed by Marisa Habibijouybari&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have used both Mongoose and Prisma in production for a few years and I want to share some experiences and information about using these two famous open source libraries. Prisma supports relational databases and it has been a while since it supports MongoDB and I think now is a good time for a comparison between these two!&lt;/p&gt;
&lt;h3&gt;
  
  
  What you will read in this article
&lt;/h3&gt;

&lt;p&gt;We are going to compare these two libraries in various parameters. Here are the areas of comparison:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learning Curve&lt;/li&gt;
&lt;li&gt;Community&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Typescript Experience&lt;/li&gt;
&lt;li&gt;Some Interesting Open Issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Learning Curve
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Mongoose Learning Curve
&lt;/h4&gt;

&lt;p&gt;Mongoose has a bit shorter learning curve in my experiments and for using it there are only a few things that you need to know to run your first query using Mongoose! A simple piece of code which is on the home page of Mongoose documentation shows how easy it is to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Connection&lt;/span&gt;
&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://127.0.0.1:27017/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Schema&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kittySchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Model&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;kittySchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="c1"&gt;// Option 1&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kitty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Zildjian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;kitty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;meow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Option 2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kitty2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Zildijan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kitty2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part is the database connection. It returns a promise but you do not need to wait for it.&lt;/p&gt;

&lt;p&gt;The second part is the &lt;strong&gt;schema&lt;/strong&gt; definition which is simply the structure of your collection. We use this schema object to create our database  &lt;strong&gt;Model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now for creating a new document in our collection, we have two options that you can see. Option one creating a new object and calling .save() method and the second option is to call Model.create({...}) .&lt;/p&gt;

&lt;p&gt;To use it we need to know two concepts of &lt;a href="https://mongoosejs.com/docs/guide.html#definition" rel="noopener noreferrer"&gt;Schema&lt;/a&gt;and &lt;a href="https://mongoosejs.com/docs/api/model.html#Model()" rel="noopener noreferrer"&gt;Model&lt;/a&gt;. We use schema to create our database model. That is the only thing you need to learn to use Mongoose.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prisma Learning Curve
&lt;/h4&gt;

&lt;p&gt;For using Prisma first thing we need is a prisma.schema file. This is a file type with its own syntax which is not so complicated and you can quickly adapt. This is where we define our collections’ structure. They all exist in this single file(which sounds not good but it has some benefits, for example, you have a version of the database structure in your version control system that you can switch into). Our connection also exists in this file(address of environment variable if we want to be more accurate).&lt;/p&gt;

&lt;p&gt;Let’s look at a schema file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;datasource&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgresql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;generator&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prisma-client-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;          &lt;span class="nb"&gt;String&lt;/span&gt;  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;id&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ObjectId&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the database source, we define the name of the env variable that we want to use for our connection string.&lt;/p&gt;

&lt;p&gt;The second part is the client and generator address which we did not pass here. Prisma creates a client API based on this schema. &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/generators" rel="noopener noreferrer"&gt;&lt;strong&gt;Generator&lt;/strong&gt;&lt;/a&gt; is important because each time we change our schema we have to run this command npx prisma generate to update &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client" rel="noopener noreferrer"&gt;Prisma Client&lt;/a&gt;(and typing of client).&lt;/p&gt;

&lt;p&gt;We need to run another script to also apply changes of schema to the database. An example is creating a new index. We have to manually apply it to the database using Migrate:&lt;br&gt;&lt;br&gt;
npx prisma migrate dev --name &lt;/p&gt;

&lt;p&gt;Now we can use our Prisma client to create a new Cat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createNewKitty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kitty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Elsa Prisma&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kitty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary of this part:&lt;/strong&gt; So overall to use Mongoose we need to understand Mongoose &lt;em&gt;Schema&lt;/em&gt; and &lt;em&gt;Model&lt;/em&gt;. For using Prisma we need to understand &lt;em&gt;schema&lt;/em&gt; definition in schema.prisma file, &lt;em&gt;Generator&lt;/em&gt;, and &lt;em&gt;Migration&lt;/em&gt;. Prisma has a longer learning curve compared to Mongoose.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community
&lt;/h3&gt;

&lt;p&gt;Both projects have quite a good community which is satisfactory. Mongoose has been around for a long time and it has a big community and eco-system. On the other hand, Prisma has a &lt;em&gt;more active&lt;/em&gt; community from my perspective. They have an active &lt;a href="https://slack.prisma.io/" rel="noopener noreferrer"&gt;Slack channel&lt;/a&gt; and also a &lt;a href="https://pris.ly/discord" rel="noopener noreferrer"&gt;Discord channel&lt;/a&gt;. We should not also underestimate the Prisma &lt;a href="https://www.youtube.com/@PrismaData/videos" rel="noopener noreferrer"&gt;Youtube Channel&lt;/a&gt; since there is a lot of good content created and they have live sessions after each release and they are presenting changes and answering questions in live.&lt;/p&gt;

&lt;p&gt;Probably the difference you see here is because Prisma is backed by a dedicated company that manages these channels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary of this part:&lt;/strong&gt; Both have a good enough community but Prisma‘s community is much more active(Supporting No-SQL is quite new).&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcwqpi4iu8k8sm4nz42r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcwqpi4iu8k8sm4nz42r.png" width="800" height="394"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Index of Documents of Mongoose and Prisma&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mongoosejs.com/docs/guide.html" rel="noopener noreferrer"&gt;Mongoose documentation&lt;/a&gt; is nice and sufficient for doing the job. The style of the documentation looks a bit old-fashioned but nothing to complain about. Prisma documentation looks modern. One thing that I find attractive in Prisma documentation is the separation of &lt;a href="https://www.prisma.io/docs/concepts" rel="noopener noreferrer"&gt;&lt;strong&gt;Concepts&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.prisma.io/docs/guides" rel="noopener noreferrer"&gt;&lt;strong&gt;Guides&lt;/strong&gt;&lt;/a&gt;. We have mentioned the Prisma learning curve, and I think good documentation covers you quite well in the process of learning Prisma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary of this part:&lt;/strong&gt; Both have really good documentation!&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;In order to compare these two libraries in terms of performance I am going to compare the queries generated by these two libraries.&lt;/p&gt;
&lt;h4&gt;
  
  
  Find By ID or something Unique
&lt;/h4&gt;

&lt;p&gt;We are trying to find a document by using something unique like _id.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuivflzmwgiro0mbo16lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuivflzmwgiro0mbo16lg.png" width="800" height="539"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;FindById Prisma vs. Mongoose&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As we can see the User.findById Mongoose directly translates to findOne({ _id: "_id" }) which is the most efficient way of fetching a document.&lt;/p&gt;

&lt;p&gt;For Prisma, it was translated to an aggregation pipeline. The first stage is $match and it contains a few single-element $and phrases and also one empty operation phrase {} . There is also a $ne with using $$REMOVE probably for &lt;a href="https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/#std-label-remove-var" rel="noopener noreferrer"&gt;conditional exclusion of fields&lt;/a&gt;. And in the end, we have a $project that exposes the fields that we have used in our Prisma Schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does using an aggregation pipeline make it slower?&lt;/strong&gt; Practically No, the speed of fetching documents highly depends on using an index(Check out my &lt;a href="https://dev.to/pshaddel/mongodb-index-challenge-learn-by-doing-39ni-temp-slug-7869961"&gt;MongoDB Index Challenge&lt;/a&gt;). After the documents have been fetched doing some extra steps like &lt;em&gt;projection&lt;/em&gt; or &lt;em&gt;addFields&lt;/em&gt; does not take a lot of time unless we have an enormous number of documents.&lt;/p&gt;

&lt;p&gt;Another interesting behavior is that if you have some extra fields in the database which does not exist on the schema, Prisma does not show them to you because it uses the projection even when you are not passing the projection object to it. But in Mongoose it returns the whole object from the database. it is not a positive or negative behavior(especially if we are using No-SQL) out of context.&lt;/p&gt;

&lt;p&gt;Generally, the Mongoose query generator seems less complicated and straightforward, but in terms of performance, I think it does not make a big difference, since most of the time we want to project some of the fields and not all of them. Especially if we have a findOne like this the projection step in the aggregation pipeline is negligible.&lt;/p&gt;
&lt;h4&gt;
  
  
  Insert Many Documents
&lt;/h4&gt;

&lt;p&gt;Queries are almost the same, on Mongoose we call insertMany (Be careful that create method generates some insertOne queries), and on Prisma we call createMany and we pass the documents.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApeRyVB_14i-fYc_R0_F6Gg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApeRyVB_14i-fYc_R0_F6Gg.png" width="800" height="372"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Inserting many documents using Prisma and Mongoose&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As we can see both generate the same insertMany queries on MongoDB, the only difference is that Mongoose generates the _id and passes it to MongoDB(We can access _id if we use new User([...])) and it can be sometimes really helpful when we want to use _id in some other objects or pass it to the response of a request.&lt;/p&gt;
&lt;h4&gt;
  
  
  Update Documents
&lt;/h4&gt;

&lt;p&gt;Updating documents is a bit different. Prisma only allows you to use a unique field for fetching a document. Beforehand it does a find(in Prisma world it is an aggregation pipeline) and returns an error if it cannot find the document! It also does another fetch after the update. So normally you have 2 more steps if you want to use Prisma for updating documents. One fetch beforehand to guarantee that the document is there and one fetch afterward to get the document. Mongoose simply translates your query to a updateMany or updateOne in MongoDB nothing more and nothing less.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFaMsi8A_hECQeFJAbvHBuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFaMsi8A_hECQeFJAbvHBuw.png" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Someone might argue that this is not a common way when you have an ODM or ORM. That’s true and when you fetch the document it gives the object with extra methods and helpers on it that you can change the object and then you can call .save() method on the object to persist it to the database, but on Prisma, there is no option for that, however, you can pass your fetched user object to update method and reassign the object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion of this part:&lt;/strong&gt; Prisma builds queries quite differently (using the Aggregation pipeline). Prisma also does an extra fetch after create or update. For update Prisma forces you to only create a folder with unique fields and also it does the fetch twice once before it and once after it.&lt;br&gt;&lt;br&gt;
Mongoose queries are quite similar(at least now!) to the way that we use MongoDB native driver, which is why I like it. Prisma used to be a SQL-ORM and probably that is the reason why its query builder behaves a bit differently. Prisma could improve itself by letting you customize this fetch behavior or even customize the logic of forcing using unique fields for updates(Let me know in the comments section if there is a way!).&lt;br&gt;&lt;br&gt;
As an end-user, you might not feel that much performance difference in my opinion.&lt;/p&gt;
&lt;h3&gt;
  
  
  Typescript Experience
&lt;/h3&gt;

&lt;p&gt;Hopefully, with the new version of Mongoose, we can create a type from a Schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;InferSchemaType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Prisma the Prisma client has already our types based on field definition in Prisma schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxAjSY_oMcrtfvBlC_2-P4Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxAjSY_oMcrtfvBlC_2-P4Q.png" width="800" height="312"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;User type in Prisma Client&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For Model Types, both give nice Type definitions.&lt;/p&gt;

&lt;p&gt;Let’s see the type definitions for queries.&lt;/p&gt;
&lt;h4&gt;
  
  
  Find Queries Typings
&lt;/h4&gt;

&lt;p&gt;Mongoose gives you the User type as the result of the find query but it unfortunately does not support typing when you project only some of the fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7rwxAU8YNzwWfnz8H-2t7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7rwxAU8YNzwWfnz8H-2t7g.png" alt="Mongoose Typing in the result of Find Query" width="800" height="316"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mongoose Typing in the result of Find Query&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To implement projection typing in Mongoose, you need a little bit of Typescript tricks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FindParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findOne&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FindParameters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;findOneWithTyping&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ProjectionType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;projection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;projection&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;projection&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;findOneWithTyping&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User not found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Error&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prisma perfectly supports the typing of projection in find queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AhVLQazTZ6GFUZY01ek9yBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AhVLQazTZ6GFUZY01ek9yBQ.png" width="800" height="208"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prisma typing in find queries&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Model Relationship Typing Support
&lt;/h4&gt;

&lt;p&gt;Both support relation typings. But Mongoose has the same problem with projection and also you do not have nested projection typings. Prisma does have these capabilities:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUGA9zgdx50dZVbX9YfUXvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUGA9zgdx50dZVbX9YfUXvg.png" width="800" height="316"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prisma Nested Projection&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Aggregation Typings Support
&lt;/h4&gt;

&lt;p&gt;Unfortunately, Mongoose does not support aggregation pipeline typings and it always types the result as any[].&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-MuxGx0jI_cor_0PPwr6cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A-MuxGx0jI_cor_0PPwr6cg.png" width="800" height="428"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mongoose Aggregation Pipeline Typing is always an array of Any&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two options for an aggregation pipeline building with Prisma. The first one uses aggregate method but it supports only a limited number of aggregation operations but it supports typing with this method:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ALxPfgDSw7Me-IUw0_D4-yA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ALxPfgDSw7Me-IUw0_D4-yA.png" width="800" height="214"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prisma Aggregate Method&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can alternatively use aggregateRaw method which supports all aggregation operations, but it does not support aggregations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEN9KctSKEwV14h-oUlQGCw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEN9KctSKEwV14h-oUlQGCw.png" width="800" height="87"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Prisma AggregteRaw Method does not support typing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary of this part&lt;/strong&gt; : Both support Typescript to some extent but Prisma supports most use cases. Mongoose is not perfect but with some extra Typescript tricks, you can build what you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some Interesting Open Issues
&lt;/h3&gt;

&lt;p&gt;At the time of writing this article Prisma has 2.7k issues and Mongoose has only 257 open issues. One of the reasons is that Prisma supports different databases and each have a lot of speciel cases and bugs. Also Mongoose has been around for a long time and most bugs are already fixed.&lt;/p&gt;

&lt;p&gt;Here we want to check out some of the debatable and interesting open issues of both.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prisma Open Issues
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/3528" rel="noopener noreferrer"&gt;Add runtime validation to models · Issue #3528&lt;/a&gt;: This issue suggests that Prisma could expose the validation function so people can check their object before trying to perform database actions. Also, some people might want to have some custom validations. This issue is open from 2020 I think. Mongoose already has this feature. I think if Prisma is not implementing this, then you could have a little bit of duplication for validation using Zod or something else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/3398" rel="noopener noreferrer"&gt;Soft deletes (e.g. &lt;code&gt;deleted_at&lt;/code&gt;) · Issue #3398&lt;/a&gt;: This is a very interesting idea! Prisma does not support it directly at the schema level but there are some ways to implement this using &lt;a href="https://github.com/prisma/prisma/issues/3398#issuecomment-688320927" rel="noopener noreferrer"&gt;Middlewares&lt;/a&gt;. Mongoose has also some workarounds that work with &lt;a href="https://stackoverflow.com/questions/43276776/mongoose-soft-delete-using-object-id" rel="noopener noreferrer"&gt;hooks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/2377" rel="noopener noreferrer"&gt;Support for splitting Prisma schema into multiple files · Issue #2377&lt;/a&gt;: This is open from 2020, people want to split their schema into multiple files. Some people have suggested some scripts to do that. You can even implement the script yourself for appending and mixing multiple files into one schema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/5042" rel="noopener noreferrer"&gt;Add &lt;code&gt;exclude&lt;/code&gt; in the query arguments · Issue #5042&lt;/a&gt;: This is also open for a long time and I think for MongoDB it is important to have this since it does support exclusion projection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/2505" rel="noopener noreferrer"&gt;Support for a Union type · Issue #2505&lt;/a&gt;: Supporting union types is also one of desirable features that users asked Prisma. They want to use multiple types(table or collection).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/298" rel="noopener noreferrer"&gt;Subscriptions/real-time API support · Issue #298&lt;/a&gt;: Having subscriptions and real time support is also another requested feature. In my perspective it is noramlly a ORM/ODM does not need to give this feature since its job is something else. But if they provide something it will save a lot of poeple a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prisma/prisma/issues/5455" rel="noopener noreferrer"&gt;Nested relations using &lt;code&gt;createMany&lt;/code&gt; · Issue #5455&lt;/a&gt;: This feature request is asking for creating nested records. For example a User could have some posts. Normally you create the user and then you create the posts and in the end you make the connection. But what if you could create the user and the posts at the same time? In my perspective this is not really common use case and I needed this feature at the time of implementing some database migrations and structural changes in the database, but looks like so many people supported the request.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mongoose Open Issues
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/Automattic/mongoose/issues/11380" rel="noopener noreferrer"&gt;Mongoose execution time increased 2 times after upgrading 4 to 6 #11380&lt;/a&gt; Mongoose had a performance issue after Mongoose 6 release and this was not due to mongo-native-driver upgrade. They are still investigating this issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Automattic/mongoose/issues/5762" rel="noopener noreferrer"&gt;new feature: virtual async #5762&lt;/a&gt; Virtuals are simply virtual fields that you can set and they exist in your object but sometimes not in your database. This feature does not support async functions and as a result people have to use some other workarounds. In my opinion it is not a major issue and you can find some good workarounds in the issue discussions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Automattic/mongoose/issues/5762" rel="noopener noreferrer"&gt;Multi-level discriminators #2851&lt;/a&gt; Discriminators help implement inheritance in Mongoose model. This feature asks for the feature of multiple discriminators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Automattic/mongoose/issues/8768" rel="noopener noreferrer"&gt;[Feature] option to disable running pre/post hooks #8768&lt;/a&gt; This requests simply disable hooks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Automattic/mongoose/issues/3812" rel="noopener noreferrer"&gt;Optimize nested populate #3812&lt;/a&gt; In a case it generates two separate queries which could be improved but it is still not implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Both libraries are really good and well-documented and well-supported and you can easily do the job with both of them. The choice really depends on your values and the context. If you value stability more than other things I think Mongoose could give you that and it will never surprise you(negative or positive). If can tolerate some minor bugs and you are curious, maybe Prisma is a better choice for you and it will definitely suprise you with new features with each release and after a while it could be your choice no matter which database you are using.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@ibezimchike/comparing-prisma-and-mongoose-fbc42d069c47" rel="noopener noreferrer"&gt;Comparing Prisma and Mongoose&lt;/a&gt;&lt;/p&gt;




</description>
      <category>mongodb</category>
      <category>node</category>
      <category>mongoose</category>
      <category>prisma</category>
    </item>
    <item>
      <title>Exploring Parallelism and Concurrency in Node.js:</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Tue, 22 Aug 2023 18:20:05 +0000</pubDate>
      <link>https://forem.com/pshaddel/exploring-parallelism-and-concurrency-in-nodejs-4joi</link>
      <guid>https://forem.com/pshaddel/exploring-parallelism-and-concurrency-in-nodejs-4joi</guid>
      <description>&lt;h3&gt;
  
  
  Exploring Parallelism and Concurrency in Node.js: Child Processes, Multithreading, Cluster, and More
&lt;/h3&gt;

&lt;p&gt;In this article, we delve into the world of parallelism and concurrency in Node.js, exploring the concepts of child processes, multithreading, and their practical implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you will read in this article
&lt;/h3&gt;

&lt;p&gt;You are going to read about the Node.js Child process, and how we can spawn a child process. Then we will look into Fork and the differences between Fork() and Unix Fork. Then we look into worker threads and clusters and in the end we shortly discuss concepts of Parallelism vs Concurrency on Nodejs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Child Process?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;child process&lt;/strong&gt; in computing is a &lt;a href="https://en.wikipedia.org/wiki/Process_(computing)" rel="noopener noreferrer"&gt;process&lt;/a&gt; created by another process (the &lt;a href="https://en.wikipedia.org/wiki/Parent_process" rel="noopener noreferrer"&gt;parent process&lt;/a&gt;). This technique pertains to &lt;a href="https://en.wikipedia.org/wiki/Computer_multitasking" rel="noopener noreferrer"&gt;multitasking operating systems&lt;/a&gt; and is sometimes called a &lt;strong&gt;subprocess&lt;/strong&gt; or traditionally a  &lt;strong&gt;subtask&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each Process could have multiple child processes and &lt;strong&gt;one parent&lt;/strong&gt;. If it does &lt;strong&gt;not have a parent process&lt;/strong&gt; it is probably created &lt;strong&gt;directly by Kernel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Specifically in Nodejs: &lt;strong&gt;Each process(Spwan or Fork) has its own memory, with its own V8 instances.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can see the process tree using this command on Mac or Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ps -axjf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gewzbezl3mrxhn53swz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gewzbezl3mrxhn53swz.png" width="800" height="163"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example of process tree&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here PID is the process ID and PPID is the parent process id. If you want to see it visualized as a tree you can use This &lt;a href="https://marketplace.visualstudio.com/items?itemName=SteveHankin.process-tree" rel="noopener noreferrer"&gt;VSCode Extension&lt;/a&gt; or install pstree with brew install pstree .&lt;/p&gt;

&lt;p&gt;For example by using this vscode extension you can see the current process tree of your machine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3olrfcwf3ac0gkpnuldj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3olrfcwf3ac0gkpnuldj.png" width="800" height="604"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Visualized Process Tree&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Spawn
&lt;/h3&gt;

&lt;p&gt;Spawn is one of the ways we can create a child process and The child_process.spawn() method spawns a new process using the given command .&lt;/p&gt;

&lt;p&gt;Let’s create a subprocess in our Nodejs app and check it out. In order to prevent processes from termination I am going to use Unix sleep command so we can see the parent-child process in the console.&lt;/p&gt;

&lt;p&gt;This is the code, we are going to use  &lt;strong&gt;Spawn&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;spawn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sleep&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Current process PID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Child process PID: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`child process exited with code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`stdout: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`stderr: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`child process exited with code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using spawn we have created a new process. Before the sleep command is over I am going to log the pid and ppid in the console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4yhu6qovg5sj788or3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4yhu6qovg5sj788or3l.png" width="800" height="139"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;It logs the current process and the child process&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2edyznhstdyvusboplnf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2edyznhstdyvusboplnf.png" width="800" height="71"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Child Parent Process&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As we can see sleep 10 command has a parent which is the process node ./spawn.js .&lt;/p&gt;
&lt;h3&gt;
  
  
  Fork
&lt;/h3&gt;

&lt;p&gt;Based on the official docs &lt;strong&gt;Fork()&lt;/strong&gt; method is a special case of&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Spawn()&lt;/strong&gt; and it is used specifically to spawn &lt;strong&gt;new Node.js processes&lt;/strong&gt;. But the child process that comes from &lt;strong&gt;Fork()&lt;/strong&gt; will have &lt;em&gt;an additional communication channel built-in that allows messages&lt;/em&gt; to be passed back and forth between the parent and child. &lt;strong&gt;This forked Nodejs process is independent of the parent and has its own V8 instance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see a simple example of a parent and forked child:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Parent.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fork&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;forkSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./fork_sort&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;forkSort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;forkSort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sorted numbers: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sortedNumbers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;forkSort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Child process exited with code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Child.js&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CHILD: message received from parent process&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedNumbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By running parent.js we can create a forked process and do the sorting in the child.js and get the result back.&lt;/p&gt;

&lt;h4&gt;
  
  
  Difference between UNIX Fork and Nodejs Child Process Fork
&lt;/h4&gt;

&lt;p&gt;In UNIX when we are forking a process, that makes a shadow of the parent's memory (they share the memory as long as they are only reading from it). this kind of memory is called &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write" rel="noopener noreferrer"&gt;Copy on Write&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here comes the big difference: &lt;strong&gt;&lt;em&gt;Nodejs fork is not a clone of the parent process. It is like Spawn(fresh memory) with a built-in communication channel!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cluster
&lt;/h3&gt;

&lt;p&gt;Using Cluster, we can run multiple instances of Node.js that can distribute workloads among their application threads.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The important thing about cluster is by using it we can easily create child processes that share the same port.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is an example(from official docs) of using Cluster for creating multiple child processes that all listen to the same port.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:cluster&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;availableParallelism&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:os&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numCPUs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;availableParallelism&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPrimary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Primary &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is running`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Fork workers.&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numCPUs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`worker &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; died`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Workers can share any TCP connection&lt;/span&gt;
  &lt;span class="c1"&gt;// In this case it is an HTTP server&lt;/span&gt;
  &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Worker &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; started`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see Cluster module has spawned some child processes using cluster.fork() .&lt;/p&gt;

&lt;p&gt;The default way that cluster module load balances the requests is that the &lt;strong&gt;primary process listens on port and accepts connections and uses round-robin&lt;/strong&gt; for distributing them to other processes.&lt;/p&gt;

&lt;p&gt;The second approach is where the primary process creates the listen socket and sends it to interested workers. The workers are able to accept incoming connections directly. ( &lt;strong&gt;In practice, distribution with this method tends to be very unbalanced due to operating system scheduler vagaries&lt;/strong&gt; )&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing using Cluster Module&lt;/strong&gt; : &lt;em&gt;Node.js does not provide routing logic. It is therefore important to design an application such that it does not rely too heavily on in-memory data objects for things like sessions and login. In other words, you cannot assign specific incoming requests to specific workers based on custom logic.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Worker Threads
&lt;/h3&gt;

&lt;p&gt;Threads are smaller units of execution within a process. Multithreading is a technique used to achieve parallelism by splitting a process into multiple threads that can execute concurrently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6axyc81kx0bwftd0w6z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6axyc81kx0bwftd0w6z.gif" width="450" height="274"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Threads vs Processes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The worker_threads module in Node.js does not create new processes; instead, it provides a way to create and manage multiple threads within the same Node.js process. This allows you to perform parallel computation without spawning separate processes.&lt;/p&gt;

&lt;p&gt;Three important things about worker threads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Workers (threads) are useful for performing CPU-intensive JavaScript operations.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;They do not help much with I/O-intensive work.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Node.js built-in asynchronous I/O operations are more efficient than Workers can be.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see a simple example before getting into the details.&lt;/p&gt;

&lt;p&gt;We want to pass our sorting operation to a worker thread. In order to do that we can have two files:&lt;br&gt;&lt;br&gt;
 1- Function that creates the worker and gets the computation result back&lt;br&gt;&lt;br&gt;
 2- Worker thread that calls sort method on the array.&lt;/p&gt;

&lt;p&gt;Here is the first file: It creates a new worker thread and resolves the promise when it gets the result back from the worker thread.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isMainThread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sortAsyncUsingWorkerThreads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sort_work_thread&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Worker stopped with exit code &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sortAsyncUsingWorkerThreads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sorted numbers: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sortedNumbers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the implementation of this worker file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;workerData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;worker_threads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;workerData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;parentPort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By just calling the postMessage method we can pass the data to the parent.&lt;/p&gt;

&lt;p&gt;In the example, each time we call this function it creates a new thread. Which is not a good idea(because we do not have unlimited worker threads available). Generally using worker threads could be tricky. Take a look at this resource from Standford University:&lt;br&gt;&lt;br&gt;
&lt;a href="https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf" rel="noopener noreferrer"&gt;https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallelism vs Concurrency in Node.js
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Concurrency in Node.js&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F701%2F1%2A0vALJbRHztQrJXsiAMi1BA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F701%2F1%2A0vALJbRHztQrJXsiAMi1BA.png" alt="Concurrency" width="701" height="216"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Concurrency&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Concurrency in Node.js refers to the ability of the system to handle multiple tasks or operations at the same time. Node.js does that by using Event Loop, it can handle a lot of requests while it is waiting for non-blocking I/O. The async-await pattern that we use daily as Node.js Developer is in order to achieve concurrency.&lt;/p&gt;

&lt;h4&gt;
  
  
  Parallelism in Node.js
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F700%2F1%2AQ7DcUO-DQ5jODVTv5Eq8UQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F700%2F1%2AQ7DcUO-DQ5jODVTv5Eq8UQ.png" width="700" height="391"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Parallelism&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Parallelism refers to the simultaneous execution of multiple tasks or processes to achieve better performance by utilizing multiple CPU cores. Node.js is inherently single-threaded, meaning it runs on a single thread of execution. However, Node.js can still achieve parallelism through various mechanisms, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Child Processes&lt;/strong&gt; : Node.js can spawn or fork multiple child processes, to take advantage of multiple CPU cores. These processes can communicate through inter-process communication mechanisms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker Threads&lt;/strong&gt; : The worker_threads module in Node.js allows developers to create and manage multiple threads within a single Node.js process. Each thread operates independently, and they can share memory, making it useful for CPU-bound tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This was a quick review of some related topics. Spawn gives a new fresh isolated process. The Fork method gives you a new Nodejs process with a built-in communication channel. Cluster is using the fork method to distribute workloads. Worker threads are good for doing CPU-Intensive tasks inside the process with shared memory.&lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/api/cluster.html#cluster_how_it_works" rel="noopener noreferrer"&gt;Cluster | Node.js v20.5.0 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/41986066/performance-and-reliability-when-using-multiple-docker-containers-vs-standard-no" rel="noopener noreferrer"&gt;Performance and reliability when using multiple Docker containers VS standard Node cluster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com/questions/47009982/node-js-clustering-vs-multiple-docker-containers#:~:text=From%20what%20I%20understand%2C%20Docker,available%20to%20the%20Docker%20container." rel="noopener noreferrer"&gt;Node.js clustering vs multiple Docker containers&lt;/a&gt;
&lt;a href="https://medium.com/media/f18f9c63e754eef625991cc9da7cf2a6/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/f18f9c63e754eef625991cc9da7cf2a6/href" rel="noopener noreferrer"&gt;https://medium.com/media/f18f9c63e754eef625991cc9da7cf2a6/href&lt;/a&gt;&lt;a href="https://medium.com/media/b8595ed54fafc0cf88e387218d752e16/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/b8595ed54fafc0cf88e387218d752e16/href" rel="noopener noreferrer"&gt;https://medium.com/media/b8595ed54fafc0cf88e387218d752e16/href&lt;/a&gt;&lt;a href="https://medium.com/media/74256cc4887a763f7414b0b2a5f7d272/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/74256cc4887a763f7414b0b2a5f7d272/href" rel="noopener noreferrer"&gt;https://medium.com/media/74256cc4887a763f7414b0b2a5f7d272/href&lt;/a&gt;&lt;a href="https://medium.com/media/c84004ddf363a9d223c8873ad93d7bfb/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/c84004ddf363a9d223c8873ad93d7bfb/href" rel="noopener noreferrer"&gt;https://medium.com/media/c84004ddf363a9d223c8873ad93d7bfb/href&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Child_process" rel="noopener noreferrer"&gt;Child process - Wikipedia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=IKG1P4rgm54&amp;amp;ab_channel=CodeVault" rel="noopener noreferrer"&gt;Difference between processes and threads — YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=hmTl5Y4ee_Y&amp;amp;ab_channel=HusseinNasser" rel="noopener noreferrer"&gt;Building a non-blocking multi-processes Web Server (Node JS fork example) — YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf" rel="noopener noreferrer"&gt;https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf&lt;/a&gt;&lt;/p&gt;




</description>
      <category>node</category>
      <category>concurrency</category>
      <category>fork</category>
      <category>spawn</category>
    </item>
    <item>
      <title>MongoDB Index Challenge: Learn by Doing!</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Sun, 11 Jun 2023 23:47:15 +0000</pubDate>
      <link>https://forem.com/pshaddel/mongodb-index-challenge-learn-by-doing-241l</link>
      <guid>https://forem.com/pshaddel/mongodb-index-challenge-learn-by-doing-241l</guid>
      <description>&lt;h4&gt;
  
  
  In this article, you will learn how indexing in MongoDB works!
&lt;/h4&gt;

&lt;h3&gt;
  
  
  What you will see in this article?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Indexes on MongoDB&lt;/li&gt;
&lt;li&gt;A list of challenges that you should choose the right index&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Introduction to Indexes on MongoDB
&lt;/h3&gt;

&lt;p&gt;If you feel totally comfortable with indexes you can skip this part and get to the challenges.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why do we need indexes?
&lt;/h4&gt;

&lt;p&gt;The answer is quite simple and indexes on the database exist for the reason that you have indexes on your phone notebook(I know that probably you do not have it now! but it was a useful thing in the past). Take a look at this notebook and say if it makes sense to start checking the notebook from the beginning to the end to find last_name of someone like “John Smith”? The answer is NO and you are directly going to the “S” section and searching there and it saves a lot of time. This is the same thing on the database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffitxrhi8gi9rj2r80j38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffitxrhi8gi9rj2r80j38.png" width="800" height="640"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Old Phone Number Notebooks&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Generally, if we do not have any index on any field, for each query we have to fetch all the documents from the Disk(which is a generally expensive operation, especially when there are a lot of documents) and then filter the desired results and return them. In MongoDB, it is called a &lt;a href="https://www.mongodb.com/docs/manual/reference/explain-results/#explain-output-structure" rel="noopener noreferrer"&gt;COLLSCAN&lt;/a&gt; which means a collection scan.&lt;/p&gt;

&lt;p&gt;For example, if this is our documents in a collection called users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jason&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sterling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this is our query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query has to perform a Collection Scan and fetch all the documents to check if they have this last_name or not.&lt;/p&gt;

&lt;p&gt;On the other hand, if we create an index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have an index exactly like our phone book. Now instead of fetching all the documents from the disk we are just fetching 1 document. In a MongoDB index, the Record_ID is stored which is the address of the document on the Disk.&lt;/p&gt;

&lt;p&gt;If you do not know a lot about indexes focus on the answers and useful links which are provided!&lt;/p&gt;

&lt;h3&gt;
  
  
  Index Challenges
&lt;/h3&gt;

&lt;p&gt;In these challenges try to avoid &lt;strong&gt;Collscan&lt;/strong&gt; and also &lt;strong&gt;in-memory sort&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In each challenge, you get the :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;document structure&lt;/li&gt;
&lt;li&gt;query(queries) that we want to perform on this collection&lt;/li&gt;
&lt;li&gt;extra information about the data if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can provide one or more indexes on the collection&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 1
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jason&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sterling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This is for warming you up!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 2 Answer&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;As you probably know we can &lt;em&gt;use the same index for searching and sorting&lt;/em&gt; at the same time! so as easy as that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge Number 2
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jason&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sterling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sterling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 2 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we are matching two different fields that we are searching for we can use &lt;a href="https://www.mongodb.com/docs/v6.0/core/index-compound/" rel="noopener noreferrer"&gt;compound indexes&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is like a phone book in that we have the indexes of family names but on each page, we are adding each person also sorted by their name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Last_Name&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;First_Name&lt;/span&gt;
&lt;span class="nx"&gt;Anderson&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Amy&lt;/span&gt;
&lt;span class="nx"&gt;Anderson&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Jim&lt;/span&gt;
&lt;span class="nx"&gt;Davis&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Amber&lt;/span&gt;
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Adam&lt;/span&gt; 
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Bruce&lt;/span&gt;
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Jane&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Pay attention that the order in the index is important!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But if you answered with this index: db.users.createIndex({ last_name: 1 }) this is also correct but it is not the best option. With this index, we will get all the documents and then &lt;strong&gt;Filter&lt;/strong&gt; the desired name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But do we need another index for the Second Query?&lt;/strong&gt; no, we do not need it! If we set this index it will be a redundant index.&lt;br&gt;&lt;br&gt;
Let’s take a look at one index and supported queries by that index to understand &lt;a href="https://www.mongodb.com/docs/manual/core/index-compound/#prefixes" rel="noopener noreferrer"&gt;prefix&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="c1"&gt;//Not needed index: ({ last_name: 1 })&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// not needed ({ last_name: 1, name: 1 })&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the above queries are supported by the compound index.&lt;/p&gt;

&lt;p&gt;Let’s get back to our challenge. Query 3: db.users.find({ name: "John" }) . If you think this could be supported by the existing index we had( ({ last_name: 1, name: 1})) You need to take a look at the Phone Book:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Last_Name&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;First_Name&lt;/span&gt;
&lt;span class="nx"&gt;Anderson&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Amy&lt;/span&gt;
&lt;span class="nx"&gt;Anderson&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Jim&lt;/span&gt;
&lt;span class="nx"&gt;Davis&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Amber&lt;/span&gt;
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Adam&lt;/span&gt; 
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Bruce&lt;/span&gt;
&lt;span class="nx"&gt;Smith&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Jane&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see there is no order for finding first names. So we have to put a single field index: db.users.createIndex({ name: 1});&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 3
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rating&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rating&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Best Newest&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Best&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// Worst Oldest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 3 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This compound index will be enough since the second one is a prefix of this index. about the third query, we must know that when we have a &lt;em&gt;sorted list we can traverse it “forward” or “backward” and still use the index&lt;/em&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 4
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// LeaderBoards&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leaderBoards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;competition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Python Hackaton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number_of_problems_solved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;competition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Python Hackaton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number_of_problems_solved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a leaderboard. Each document has a “competition field” which is the name of the competition and each person has a “score”. We also keep a number of problems that are solved and resulted in this score.&lt;br&gt;&lt;br&gt;
This is the query we want to perform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 4 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leaderBoards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
   &lt;span class="na"&gt;competition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Python Hackaton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
   &lt;span class="na"&gt;number_of_problems_solved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$lte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this query, we want to get userId of the people who have the best score, but we expect them to have this score for solving less than 10 problems.&lt;/p&gt;

&lt;p&gt;Our suggestion for the index is this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leaderBoards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="na"&gt;competition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;number_of_problems_solved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But Why? There is a simple rule called: &lt;a href="https://www.mongodb.com/docs/manual/tutorial/equality-sort-range-rule/" rel="noopener noreferrer"&gt;ESR&lt;/a&gt; (Equality, Sort, Range)&lt;/p&gt;

&lt;p&gt;The first field we are indexing is competition. Since equality comparison usually can filter lots of documents it makes sense to put this as the first field in our compound index. (if for example, 95% of the documents have this field competetion with value of Python Hackaton then it might not make sense to use it as the first field — in other words, our equality filter is not &lt;strong&gt;Selective&lt;/strong&gt; enough).&lt;/p&gt;

&lt;p&gt;The second field in the compound is score. But why are we using the sort field as the second? The intention is &lt;strong&gt;to prevent In Memory Sort&lt;/strong&gt;. If we use our range in the second field of the compound index then we cannot use the sort index anymore.&lt;/p&gt;

&lt;p&gt;This is the result of the current index:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g3fzaagfo3uuoj8po0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5g3fzaagfo3uuoj8po0e.png" width="800" height="83"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;With the current index — no in-memory search&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we use this index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;competition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;number_of_problems_solved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x7mgiz6tokfxdc5epxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x7mgiz6tokfxdc5epxg.png" width="800" height="83"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;without ESR Rule we face in-memory sort&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you can see we had to do a in-memory sort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do we have to always follow ESR Rule to prevent in-memory sorting?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer is NO! If the situation is somehow that &lt;strong&gt;the range field is really selective and eliminates most of the documents&lt;/strong&gt; and you do not have a lot of documents left to sort, then it makes more sense to put this field as the second field of the index. In this case, we are sorting in memory but we might have better results. If you are still not sure, you can have both indexes for a period of time and see which one is chosen by the query optimizer(the query optimizer runs queries with these indexes at the same time to check which one is better — By default, it avoids the in-memory sort).&lt;/p&gt;
&lt;h3&gt;
  
  
  Challenge Number 5
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;weight&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IPhone 14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IPhone 14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IPhone 14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$lte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Filter products with less than 2 kg weight&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Extra Information&lt;/strong&gt; : &lt;em&gt;Field weight does not exist on more than half of the products&lt;/em&gt;(but we do not want to have these documents in the result)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 5 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Partial Index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;partialFilterExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$exists&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Alternative Solution&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;wight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sparse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using a &lt;a href="https://www.mongodb.com/docs/manual/core/index-partial/" rel="noopener noreferrer"&gt;partial index&lt;/a&gt; and adding a partial filter expression we can ask MongoDB to not index documents that we do not want. If you have a collection with a few million documents and you are querying on a specific field that only a minority of the documents have this field, Partial Index can be helpful with two benefits: &lt;strong&gt;1- Smaller Index 2- Faster Look Up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another alternative is using the sparse option. Only indexes if the field exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another usage of Partial Indexes&lt;/strong&gt; is in a situation where you are running a range query. For example, you never filter products that have a &lt;strong&gt;rating&lt;/strong&gt; of less than 2(worst products). So why index them? we can use this index on rating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ourIndex&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;partialFilterExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But keep in mind that if now you run a query like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This results in a collection index!&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 6
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;office&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wood&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;laptop_desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IPhone 14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;phone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// Filter apple products&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 6 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Multikey Index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This index will index each element of the array! this works on fields that are arrays like: [1, 2, 3] and also fields that are documents or nested documents .&lt;/p&gt;

&lt;h4&gt;
  
  
  Limitations
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You cannot have 2 multikey indexes in a compound index(the number of indexes will be n*m)&lt;/li&gt;
&lt;li&gt;Cannot use covered queries. (Covered queries are the queries that all needed fields that exist in the index you do not need to fetch documents from the disk)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are some other limitations too that you can check &lt;a href="https://www.mongodb.com/docs/manual/core/index-multikey/#limitations" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 7
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a brown desk for usage in office or home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IPhone 14&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hight quality product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ISO_DATE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-05-11&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brown desk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Challenge 7 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Text Index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// Text Index with another collation to support lowercase uppercase&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;collation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;local&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;strength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://www.mongodb.com/docs/manual/core/index-text/" rel="noopener noreferrer"&gt;text index&lt;/a&gt; is also supported by MongoDB and we can use it. But keep in mind that it works similarly to the multikey index! It means that it is kind of similar to having an array of strings and putting a multikey index on this array.&lt;/p&gt;

&lt;p&gt;And the limitation is that you can use it on only a field in your collection. But if you are using &lt;a href="https://www.mongodb.com/atlas/search" rel="noopener noreferrer"&gt;Atlas Search&lt;/a&gt; is a much much better option to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge Number 8
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Poorshad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shaddel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userMetadata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;likes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dogs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userMetadata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dislikes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pickles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inactive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Queries&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dislikes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pickles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inactive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Extra Information&lt;/strong&gt; : userMetadata has an arbitrary structure but we want to have an index on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 8 Answer&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Wild Card Index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userMetadata.$**&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this case, we have to use a &lt;a href="https://www.mongodb.com/docs/v6.0/core/index-wildcard/" rel="noopener noreferrer"&gt;Wild Card Index&lt;/a&gt;. We can index all the fields that fit in this pattern. If you are putting a lot of stuff into this object and you are not querying most of them, it might not be the best idea to use userMetadata.&lt;/p&gt;

&lt;p&gt;Another pattern we could use to store this arbitrary data in the index was to &lt;a href="https://dev.to/mongodb/building-with-patterns-the-attribute-pattern-299m-temp-slug-2892504"&gt;Attribute Pattern&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attribute&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;likes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attribute&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can use an index like this to support the queries on this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary Of Challenges
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-single/" rel="noopener noreferrer"&gt;Challenge Number 1(Single Index)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-compound/" rel="noopener noreferrer"&gt;Challenge Number 2(Compound Index)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/tutorial/sort-results-with-indexes/#sort-with-a-single-field-index" rel="noopener noreferrer"&gt;Challenge Number 3(Sort Direction)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/tutorial/equality-sort-range-rule/" rel="noopener noreferrer"&gt;Challenge Number 4(ESR)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/v6.0/core/index-partial/" rel="noopener noreferrer"&gt;Challenge Number 5(Partial Index)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-multikey/" rel="noopener noreferrer"&gt;Challenge Number 6(Multikey Index)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-text/" rel="noopener noreferrer"&gt;Challenge Number 7(Text Index)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-wildcard/" rel="noopener noreferrer"&gt;Challenge Number 8(Wildcard index)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Next Steps to Explore More
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/index-hashed/" rel="noopener noreferrer"&gt;Hashed Indexes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/2d/" rel="noopener noreferrer"&gt;2D Indexes&lt;/a&gt;&lt;/p&gt;




</description>
      <category>challenge</category>
      <category>indexing</category>
      <category>performance</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>How MongoDB Clustered Collection Can Boost Query Performance</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Sun, 28 May 2023 17:08:33 +0000</pubDate>
      <link>https://forem.com/pshaddel/how-mongodb-clustered-collection-can-boost-query-performance-1ojn</link>
      <guid>https://forem.com/pshaddel/how-mongodb-clustered-collection-can-boost-query-performance-1ojn</guid>
      <description>&lt;p&gt;Mongodb Clustered Collection is a relatively new feature released in MongoDB 5.3 that could improve query performance!&lt;/p&gt;

&lt;h4&gt;
  
  
  What you will read in this article
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;How does MongoDB fetch documents in a collection&lt;/li&gt;
&lt;li&gt;How does Mongodb fetch documents in a clustered collection&lt;/li&gt;
&lt;li&gt;Limitation&lt;/li&gt;
&lt;li&gt;Playing with Clustered and Normal Collection&lt;/li&gt;
&lt;li&gt;When to use Clustered Collection&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How does MongoDB fetch documents in a normal collection?
&lt;/h3&gt;

&lt;p&gt;Here we want to discuss how MongoDB fetches documents using indexes. If there is no index MongoDB has to fetch all documents in a process called COLLSCAN if you look at the query explainer. COLLSCAN fetches all documents of a collection from the disk and then starts doing your desired operation. Here we focus on what happens when you are using an index.&lt;/p&gt;

&lt;p&gt;Imagine you are using _id which is indexed(by default) and you want to fetch one document. Here is what happens:&lt;/p&gt;

&lt;h4&gt;
  
  
  Find the _id in the MongoDB BPlus Tree
&lt;/h4&gt;

&lt;p&gt;Indexes in MongoDB are stored in a BPlus Tree. If you do not know what is a &lt;a href="https://en.wikipedia.org/wiki/B%2B_tree" rel="noopener noreferrer"&gt;BPlus Tree&lt;/a&gt; it is similar to a BTree with two major differences:&lt;/p&gt;

&lt;p&gt;1- Values are at leaves.&lt;br&gt;&lt;br&gt;
2- Leaves have pointer to the next one(which makes it fast for range queries)&lt;/p&gt;

&lt;p&gt;This is a simple BTree consisting of these numbers: (1,2,3,4,5,6,9,10)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7rgxqwjtib2p2nsbevx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7rgxqwjtib2p2nsbevx.png" alt="BTree consisting 1,2,3,4,5,6,9,10" width="800" height="238"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;BTree consisting 1,2,3,4,5,6,9,10&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is on the other hand a B+Tree consisting of the same numbers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7emr70o9tst77llk1dae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7emr70o9tst77llk1dae.png" width="800" height="238"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;B+Tree consisting 1,2,3,4,5,6,9,10&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;MongoDB stores indexes in B+ Tree so when we are running this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.users.findOne({ _id: ObjectID("...") });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing MongoDB does is it goes to this B+ Tree and finds the _id.&lt;/p&gt;

&lt;p&gt;Now it got the Leaf. &lt;strong&gt;&lt;em&gt;But the important thing is that your document is not the value of this Leaf&lt;/em&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
the value is another thing called &lt;strong&gt;RecordID&lt;/strong&gt;. MongoDB has a hidden clustered index which is another B+ Tree that you can find the document by using &lt;strong&gt;RecordID&lt;/strong&gt;. You have to traverse the tree once again and you have your document.&lt;/p&gt;

&lt;p&gt;So the summary of what happens with this simple search query:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1- Traverse the B+ Tree and find the Leaf regarding _id or any indexed field you have&lt;br&gt;&lt;br&gt;
2- Get RecordID from the Leaf.&lt;br&gt;&lt;br&gt;
3- Traverse the hidden clustered index for RecordID&lt;br&gt;&lt;br&gt;
4- Get the document from Value of RecordID&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  How does Mongodb fetch documents in a clustered collection?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;In a clustered collection you do not have a RecordID anymore!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You need to traverse the B+ Tree only once and you have the document!&lt;/p&gt;

&lt;p&gt;As simple as that. We should be careful with this since we know everything comes at a cost.&lt;/p&gt;
&lt;h4&gt;
  
  
  Cost of using Clustered Documents
&lt;/h4&gt;

&lt;p&gt;In a normal collection you only had RecordID, as a result when we added more indexes we do not see that many changes in the size of the collection. But now if we add more indexes we see big changes. &lt;strong&gt;If you do not add more indexes the size of the clustered collection is smaller than the normal collection because we do not have this RecordID.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;By default, if a &lt;a href="https://www.mongodb.com/docs/manual/reference/glossary/#std-term-secondary-index" rel="noopener noreferrer"&gt;secondary index&lt;/a&gt; exists on&lt;br&gt;&lt;br&gt;
a clustered collection and the secondary index is usable by your&lt;br&gt;&lt;br&gt;
query, the secondary index is selected instead of the clustered&lt;br&gt;&lt;br&gt;
index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can use clustered index only on _id field!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You cannot convert a normal collection to a clustered collection or vice versa.&lt;/p&gt;
&lt;h3&gt;
  
  
  Playing with Clustered and Normal Collection
&lt;/h3&gt;

&lt;p&gt;I want to create two collections on MongoDB Atlas and run some queries on them:&lt;/p&gt;

&lt;p&gt;For creating a clustered collection we can use the UI and easily choose the clustered collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybqng146ibtel7i833oq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybqng146ibtel7i833oq.png" width="800" height="717"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Create a Clustered Collection&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Also, let’s create a normal collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdiwzooz992gs0u9cf1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdiwzooz992gs0u9cf1e.png" width="800" height="517"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Normal Collection&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now if we run a findOne({ _id: “”}) we can see the difference in explain query.&lt;/p&gt;

&lt;p&gt;The first one is for transactions_original which uses the _id index and chooses IDHACK(the name of the plan when we use _id to find a document)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fog3zw53erz09qgzmods9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fog3zw53erz09qgzmods9.png" width="800" height="364"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;IDHACK&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For the clustered collection we can see that the query plan selected was CLUSTERED_IXSCAN&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon8qa54ckurgdn8otnkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fon8qa54ckurgdn8otnkt.png" width="800" height="364"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;CLUSTERED_IXSCAN&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s also see the difference in the size of the index for 100k documents:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmek36ym1v0bi587b1mo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmek36ym1v0bi587b1mo4.png" width="800" height="75"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Clustered Index Size&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AV_cc2Qc8RF4BeFH7VuQSMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AV_cc2Qc8RF4BeFH7VuQSMA.png" width="800" height="75"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Normal Index Size&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s perform some queries on a new collection called products. Our usage is that we fetch products that have better ratings(mostly range queries).&lt;/p&gt;

&lt;p&gt;Then we put 1 million products. For comparison, we create also products_original . In order to use clustered index we put rating of product into _id of products .&lt;/p&gt;

&lt;p&gt;For products_original this is the schema and the query we want to perform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// products_original 
{
  _id: ObjectID("..."),
  rating: number =&amp;gt; index(-1),
  name: string
}
Query = db.collection.find({ rating: { $gte: 0.9 } })

// products_clustered
{
  _id: clusteredIndex(we put rating into this field),
  productId: uuidv4(),
  name: string,
}
Query = db.collection.find({ _id: { $gte: 0.9 } })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I created 1M products and for making the comparison fair I used the same ratings for these 1M products. The data in both collections is the same. This is not a benchmark that you can rely on but the result and query explain data might give you some idea that when it is worth using.&lt;/p&gt;

&lt;h4&gt;
  
  
  Result of the range query in the Clustered Collection
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABGt4GYgN04hkIP34-naoeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABGt4GYgN04hkIP34-naoeQ.png" width="800" height="542"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Range Query Using Clustered Index&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Result of the range query in the Normal Collection
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ah_G-LKfCCi0LccTsVrDMTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ah_G-LKfCCi0LccTsVrDMTA.png" width="800" height="542"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Range Query Result in Normal Collection&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In normal collection one apparently expensive step was Fetch! Because for each _id we have to look up the RecordID and then get the documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use Clustered Collection
&lt;/h3&gt;

&lt;p&gt;There is not a special description for this in the documentation but based on the list of benefits we can summarize that like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries with range scans and equality comparisons on
the clustered index key&lt;/li&gt;
&lt;li&gt;Faster bulk insert&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=OhJ3xcjtpis&amp;amp;ab_channel=HusseinNasser" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=OhJ3xcjtpis&amp;amp;ab_channel=HusseinNasser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/docs/manual/core/clustered-collections/" rel="noopener noreferrer"&gt;Clustered Collections&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Level Up Coding
&lt;/h3&gt;

&lt;p&gt;Thanks for being a part of our community! Before you go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👏 Clap for the story and follow the author 👉&lt;/li&gt;
&lt;li&gt;📰 View more content in the &lt;a href="https://levelup.gitconnected.com/?utm_source=pub&amp;amp;utm_medium=post" rel="noopener noreferrer"&gt;Level Up Coding publication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💰 Free coding interview course ⇒ &lt;a href="https://skilled.dev/?utm_source=luc&amp;amp;utm_medium=article" rel="noopener noreferrer"&gt;View Course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔔 Follow us: &lt;a href="https://twitter.com/gitconnected" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/company/gitconnected" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://newsletter.levelup.dev" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀👉 &lt;a href="https://jobs.levelup.dev/talent/welcome?referral=true" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Level Up talent collective and find an amazing job&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>clusteredcollection</category>
      <category>database</category>
      <category>databasedesign</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>From Java and Microservices to Dgraph: A Big Bang Migration Journey of a 14M Users App</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Thu, 25 May 2023 02:46:47 +0000</pubDate>
      <link>https://forem.com/pshaddel/from-java-and-microservices-to-dgraph-a-big-bang-migration-journey-of-a-14m-users-app-3g49</link>
      <guid>https://forem.com/pshaddel/from-java-and-microservices-to-dgraph-a-big-bang-migration-journey-of-a-14m-users-app-3g49</guid>
      <description>&lt;p&gt;The story of a big bang migration that we had in one of the companies where I worked!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F299vbuf6k5kb19d9orcr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F299vbuf6k5kb19d9orcr.png" width="800" height="653"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Dgraph&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What you will read in this article?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;About the application and the team&lt;/li&gt;
&lt;li&gt;Why we had to migrate the technology?&lt;/li&gt;
&lt;li&gt;What is Dgraph? Could a Database replace the Backend?&lt;/li&gt;
&lt;li&gt;How We Have Done the Migration with New Data Structure&lt;/li&gt;
&lt;li&gt;The problem of Caching in GraphQL&lt;/li&gt;
&lt;li&gt;Security Issues in GraphQL&lt;/li&gt;
&lt;li&gt;How we Built a Custom UI using GraphQL&lt;/li&gt;
&lt;li&gt;How We Have Used Elastic Search Directly on Dgraph&lt;/li&gt;
&lt;li&gt;Regrets and Expriences&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  About the application
&lt;/h4&gt;

&lt;p&gt;Before getting to the details I want to clarify what was the application. It was a video streaming application and also users had access to a selected archive of the content(each content stored in the platform based on its program’s priority). Most people have used this application for watching important football games or famous local TV series. This application had about ~14M users at that time and in the pick time, we were experiencing around 800K-900k concurrent users.&lt;/p&gt;

&lt;p&gt;Our Backend Before Migration: Java/MySQL Microservice Architecture&lt;/p&gt;

&lt;p&gt;After Migration: Dgraph/ Elixir Phoenix for Authentication&lt;/p&gt;

&lt;p&gt;Our Frontend was Angular and remained the same.&lt;/p&gt;
&lt;h4&gt;
  
  
  Size of the Team
&lt;/h4&gt;

&lt;p&gt;1 Backend Developer(I) — 2 Frontend Developers — 3 Site Reliability Engineers — Engineering Manager and CTO. Overall 8 persons.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why We Had to Migrate the Technology?
&lt;/h3&gt;

&lt;p&gt;If you are reading here to see that the performance issue was related to the programming language, I have to say you are in the wrong place, and without a doubt &lt;em&gt;Java was not the problem&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These were the problems in my personal opinion:&lt;/p&gt;
&lt;h4&gt;
  
  
  1- Lack of coherence in the Backend Repository
&lt;/h4&gt;

&lt;p&gt;This was the result of having a small team and most of the time it was one person or in some cases, two persons working on the backend side of this project and it resulted in a code base with different strategies. Probably because the developer was the only one working on the code base it was hard to standardize the code. Also in teams without enough resources for growth, there are lots of tasks and bugs that are expected to be tackled before other important things like documentation, tests or standardization.&lt;/p&gt;
&lt;h4&gt;
  
  
  2- Lack of Documentation
&lt;/h4&gt;

&lt;p&gt;There was no documentation about the code and how it works and even why some features exist. We had to communicate with different people to find out something is needed or not. The management has never asked for something like this in the first place so no one created any documentation about the code.&lt;/p&gt;
&lt;h4&gt;
  
  
  3- Inflexibility
&lt;/h4&gt;

&lt;p&gt;Based on the estimation that the backend team(with different seniority levels and range of skills) was giving for small features or bug fixings it was obvious that the code has lost its flexibility and they are not able to ship fast and change the code.&lt;/p&gt;
&lt;h4&gt;
  
  
  4- No Knowledge Transfer
&lt;/h4&gt;

&lt;p&gt;After the last Backend Developer left the company we had to deal with a Backend Repository without documentation or any clues. unfortunately there was no process of knowledge transfer so we had no choice except to go to into maintenance mode for a while.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;What is Dgraph? Could a Database Could Replace the Backend?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We wanted to ship a lot of features fast and the number of users was increasing so we needed also a scalable solution. We finally decided to rewrite the whole backend but there were some problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It was huge and had a lot of logic&lt;/li&gt;
&lt;li&gt;We did have only a few months at most for rewriting the whole thing and the Team was super small&lt;/li&gt;
&lt;li&gt;At the same time, there were expected new features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A year before this migration our CTO told me about an interesting Database called &lt;a href="https://dgraph.io/" rel="noopener noreferrer"&gt;Dgraph&lt;/a&gt; and I started following this database newsletter and joined the forums of the community.&lt;/p&gt;

&lt;p&gt;At that time it just introduced the &lt;em&gt;GraphQL APIs&lt;/em&gt; which was amazing. If you’ve never heard about Dgraph it is a Graph Database written with Go Lang and besides being a database it offers API’s based on your Schema. This schema is a simple GraphQL Schema with some extra directives specific to Dgraph. When you define your schema you already have the API’s.&lt;/p&gt;

&lt;p&gt;For example, if you define this schema in your Dgraph GraphQL Schema(The environment is Dgraph Cloud):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvke6r9kct8c3i1eknov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvke6r9kct8c3i1eknov.png" width="800" height="340"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Dgraph GraphQL Schema Deployment and Definition&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ID&lt;/strong&gt; is a unique type and it is created by Dgraph DB itself.&lt;/p&gt;

&lt;p&gt;Now we have a GraphQL Schema that we can use:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4kz8lkjcbrx95f199iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy4kz8lkjcbrx95f199iy.png" width="800" height="275"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;GraphQL API’s Based on GraphQL Schema&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For each type by default you have these API’s generated:&lt;/p&gt;

&lt;p&gt;1- aggregate[TypeName]&lt;br&gt;&lt;br&gt;
2-get[TypeName]&lt;br&gt;&lt;br&gt;
3-query[TypeName]&lt;br&gt;&lt;br&gt;
4-add[TypeName]&lt;br&gt;&lt;br&gt;
5-update[TypeName]&lt;br&gt;&lt;br&gt;
6-delete[TypeName]&lt;/p&gt;

&lt;p&gt;At the time I started following Dgraph it did not support authorization and customized access to these functionalities but after six months they introduced &lt;a href="https://dgraph.io/docs/graphql/schema/directives/auth/" rel="noopener noreferrer"&gt;Authentication Directive&lt;/a&gt; on GraphQL Schema which made it production ready in my perspective and we could handle a lot of cases.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why did Our Team think Dgraph was a good solution?
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1-Time Restriction&lt;/strong&gt; : First of all we did not have that much time and we had to do this migration in a few months and in between a big Cyber Attack happened and moved the deadline to a sooner date. So it was not possible to implement more than hundred different routes with high test coverage. On the other hand, using GraphQL API of Dgraph could save us a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2-Our Application Behavior&lt;/strong&gt; : Our application &lt;em&gt;had more reads than writes&lt;/em&gt; and most of these reads were the result of complicated queries from joining more than 3 tables. &lt;em&gt;A lot of joins and heavy queries send us the signal that we might have some benefits if we use a Graph Database&lt;/em&gt; &lt;strong&gt;.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Another important thing that motivated us was that Dgraph had introduced something called &lt;a href="https://dgraph.io/docs/graphql/custom/custom-dql/" rel="noopener noreferrer"&gt;Custom DQL&lt;/a&gt; . DQL is the language of Dgraph Database. &lt;em&gt;This feature lets us implement custom complicated queries(Something like MongoDB aggregation pipeline) and put these queries behind GraphQL API’s&lt;/em&gt;. Pagination was also included without any problem and in our case, a lot of already existing Backend API’s were just returning a complicated query from MySQL. So this feature was also saving us a lot of time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3- Lambda Resolvers For Our Custom Logic:&lt;/strong&gt; We knew that we need some to implement some custom logic. For this need, Dgraph offered &lt;a href="https://dgraph.io/docs/graphql/lambda/lambda-overview/" rel="noopener noreferrer"&gt;Lambda Resolvers&lt;/a&gt; which are equivalent to Lambda Functions but with the difference that Lambda Resolvers are web workers.&lt;/p&gt;
&lt;h4&gt;
  
  
  Could Dgraph Database Replace the Backend?
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;The answer is Yes and No!&lt;/em&gt;. There are more options these days that are working in the same way as &lt;strong&gt;Dgraph&lt;/strong&gt;. &lt;a href="https://neo4j.com/developer/graphql/" rel="noopener noreferrer"&gt;Neo4J&lt;/a&gt; got the good idea(in my opinion maybe from Dgraph or &lt;a href="https://www.graphile.org/postgraphile/" rel="noopener noreferrer"&gt;Postgraphile&lt;/a&gt;) and now offers a super nice GraphQL API for the database with a lot of features. It seems that it is easier for Graph Databases to offer a GraphQL API but &lt;a href="https://hasura.io/" rel="noopener noreferrer"&gt;Hasura&lt;/a&gt; offers it with Relational Databases.&lt;/p&gt;

&lt;p&gt;The point here is that people are using API’s from these databases(or platforms) instead of implementing every single route in a backend. We can have our own custom logic in each one of these platforms that I mentioned. Even if we are not satisfied with the database custom logic handling we can have a small backend on the side that works with the database and does some of the complicated things for us.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;How We Have Done the Migration with new Data Structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We started with a proof of concept to see if we are able to do this or not and let’s see how is the performance with some of our complicated queries.&lt;/p&gt;

&lt;p&gt;For migrating SQL data to Dgraph there is a tool that Dgraph implemented but we did not want to use it because we had to also change the data structure.&lt;/p&gt;

&lt;p&gt;We were providing Video content and everything was implemented in a hierarchy. For example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzl8i63sxeotqiod6h7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzl8i63sxeotqiod6h7e.png" width="800" height="361"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Hierarchy of Categories&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each of these categories had some subcategories. Each content had one of the leaves in this tree. We decided to go with the concept of Tags instead of using Tree(or both at the same time). We had a lot of tables and structures to assign different attributes, categories and subcategories to each content, but from a Tag perspective, all of these attributes could be considered as some Tags that we could assign to the Content and this drastically reduced the complexity .&lt;/p&gt;

&lt;p&gt;In the older system content had a leaf called: PrimaryLeague but in the new system it had a tags fields that should contain all parents of content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
tags: [
  {uid: 0x1, name: 'primaryLeague'},
  {uid: 0x2, name: 'football'},
  {uid: 0x3, name: 'international'},
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Database Converter and Challenges
&lt;/h4&gt;

&lt;p&gt;For migrating Data, We have used &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;. The reason we used Prisma was the &lt;a href="https://www.prisma.io/docs/concepts/components/introspection" rel="noopener noreferrer"&gt;Database Pull Feature&lt;/a&gt;. We had the production database structure and with this command, I was able to convert all the tables to a Prisma Schema: npx prisma db pull .&lt;/p&gt;

&lt;p&gt;After that running npx prisma generate updated the Prisma Client and we had access to all tables and their relations in Typescript so I was able to fetch data and convert them to the new structure and insert them into the new database. Dgraph had a official &lt;a href="https://github.com/dgraph-io/dgraph-js" rel="noopener noreferrer"&gt;Nodejs Client library&lt;/a&gt; for using DQL queries and mutations that we have used for this matter.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One of the biggest challenges was connecting Dgraph Nodes and creating the reverse edges&lt;/em&gt;. For connecting the Graph Nodes you need UID of the Nodes and the problem was that you cannot set this UID, dgraph generates this UID. So I had to create both Nodes at one step, then fetch the nodes and finally run an update query to connect these nodes. This was mostly the reason why this &lt;strong&gt;Database Converter&lt;/strong&gt; was not so fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Problem of Caching in GraphQL&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Caching is usually not easy for GraphQL API since most caching processes are working with URL rather than details of the request. Parsing the request content was expensive for us since the number of concurrent requests were always high(most of the time more 10K). So we came up with the idea of hashing the queries and sending them from the client side. For each common query we were hashing the query content and we added this as queryId to the endpoint. Now we were able to do the caching. We could also set the caching time of each endpoint by using &lt;a class="mentioned-user" href="https://dev.to/cache"&gt;@cache&lt;/a&gt; directive on Dgraph Schema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Issues in GraphQL
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Failure to Appropriately Rate-limit
&lt;/h4&gt;

&lt;p&gt;This is one the queries that could cause problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query Recurse {
  allUsers {
    posts {
      author {
        posts {
          author {
            posts {
              author {
                posts {
                  id
                }
              }
            }
          }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attacker can nest this query a lot and as a result it puts a lot of pressure on the database.&lt;/p&gt;

&lt;p&gt;For solving this issue we had to put a minimal Shield for protection against this kind of queries. We limited the size of query and also response to a small number and as a result this query which is passed could not be so big. We set the query timeout number in Dgraph to 1 Second(it means it drop the queries that take more than this number).&lt;/p&gt;

&lt;p&gt;Also Dgraph have a feature for rate limiting that we have used along side these options I explained and you can check the details here: &lt;a href="https://dgraph.io/docs/deploy/cli-command-reference/#limit-superflag" rel="noopener noreferrer"&gt;https://dgraph.io/docs/deploy/cli-command-reference/#limit-superflag&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  User Could Get All Documents From Dgraph GraphQL API
&lt;/h4&gt;

&lt;p&gt;This was also another issue that the client could set page size. We limited the response size and as a result no one can easily get this data but they could harm the database performance. So we had to handle this also in our Go Lang Shield. We set the page size in there and as a result you cannot pass your desired page size to the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How We Built a Custom UI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the pains we had in there was too many changes in the UI of the application both in the Website and Mobile Apps. Not major changes but moving components around. We already had some components which were well implemented. We came up with a page, component system to handle these changes and at the same time introduced the feature of custom pages for different channels and events. These custom pages usually took a lot of time from our Fronted Developers so it having this feature could save them a lot of time.&lt;/p&gt;

&lt;p&gt;This is a simplified version to show you the idea of how this UI was implemented:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzc1dotks8ot3xtobfdt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzc1dotks8ot3xtobfdt.png" width="637" height="536"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Simple UI Component Structure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our Frontend Developers and Mobile Developer used the same component names and the design system was somehow that they could both read our pages and generate the UI. Support users were able to do all the customization with different kinds of components.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How We Have Used Elastic Search Directly on Dgraph&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First we started the new version by using &lt;a href="https://dgraph.io/docs/query-language/functions/#fuzzy-matching" rel="noopener noreferrer"&gt;Dgraph Fuzzy Matching&lt;/a&gt; and later with some complicated queries to get related contents. It was not efficient enough and we were not able to get related content when the search phrase was not so accurate or it was more than a word. As a result we decided to use &lt;a href="https://www.elastic.co/" rel="noopener noreferrer"&gt;Elastic Search&lt;/a&gt; for our search functionality. One of the teamates has implemented a small service with Elixir for syncing our Dgraph Database with Elastic Search(Not the whole database just 2 types).&lt;br&gt;&lt;br&gt;
Now we had to find a way to perform our search queries. The first way that came to mind was to implement a minimal backend to access these search queries, but we had to think about scaling this small service and again we were facing all the problems. &lt;em&gt;In the end we came up with a solution to expose one GraphQL API that requested data from our Elastic Search&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By using &lt;a href="https://dgraph.io/docs/graphql/custom/query/" rel="noopener noreferrer"&gt;Dgraph Custom Queries&lt;/a&gt; you can make HTTP Requests to other endpoints and parse the result and return it in a GraphQL Resolver.&lt;/p&gt;

&lt;p&gt;Check out this article on Dgraph for the details of &lt;a href="https://discuss.dgraph.io/t/how-we-connected-elastic-search-to-dgraph/15151" rel="noopener noreferrer"&gt;how we connected Dgraph to Elastic Search&lt;/a&gt;. Below you can see a schematic of how this is handled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4n0yred47o9x03ilhuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4n0yred47o9x03ilhuv.png" width="800" height="170"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How Dgraph is Connected to Elastic&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Regrets and Experiences&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Not enough Documentation
&lt;/h4&gt;

&lt;p&gt;Dgraph did not have a perfect documentation at the time and I had to learn all the tricks from &lt;a href="https://discuss.dgraph.io/" rel="noopener noreferrer"&gt;Dgraph Forum&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Investors Fired CEO(Founder) of Dgraph
&lt;/h4&gt;

&lt;p&gt;After we almost finished our migration this happend and the whole Dgraph Team resigned and It was super scary for me. Now it has another CEO and they are going in a good path and their steadily improving features and fixing bugs.&lt;br&gt;&lt;br&gt;
Read more about this:&lt;br&gt;&lt;br&gt;
 &lt;a href="https://www.reddit.com/r/golang/comments/sfl7kj/quitting_dgraph_labs/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/golang/comments/sfl7kj/quitting_dgraph_labs/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://discuss.dgraph.io/t/going-out-of-business/16631" rel="noopener noreferrer"&gt;https://discuss.dgraph.io/t/going-out-of-business/16631&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A Lot of Try and Error to Optimize Queries Based on Data
&lt;/h4&gt;

&lt;p&gt;After a while some our queries changed and the reason behind it was the shape of our data. We had some Types with more than a few Million records and in queries we had to avoid running queries like Regex or Full-Text Search as much as possible.&lt;/p&gt;

&lt;p&gt;An example of design change because of optimizing query:&lt;br&gt;&lt;br&gt;
First we had Content and Tag but querying contents with specific tags was really expensive and we had to touch all contents. We made the relation two way and then we were able to get the contents from tag(Indexes are removed for simplicity).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry1bpyt8mt8dizfx766o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry1bpyt8mt8dizfx766o.png" width="800" height="474"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two Different Approach for getting contents that have specific tag&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the first design for getting contents that have specific tag we must touch all contents(which was over a few million nodes). With second approach we directly get the tag and the contents are attached to this node so it is super fast compared to previous approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFI7GeuAUGNWGq812R2fW9A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFI7GeuAUGNWGq812R2fW9A.png" alt="Two different queries for getting contents that have specific tag" width="800" height="652"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two different queries for getting contents that have specific tag&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Some Dgraph Issues that made us Slow
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://discuss.dgraph.io/t/dgraph-manual-reverse-index-is-gone-after-each-graphql-schema-upload/14829" rel="noopener noreferrer"&gt;https://discuss.dgraph.io/t/dgraph-manual-reverse-index-is-gone-after-each-graphql-schema-upload/14829&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://discuss.dgraph.io/t/cannot-query-after-deleting-an-entity-that-is-used-in-a-union-type/15483" rel="noopener noreferrer"&gt;https://discuss.dgraph.io/t/cannot-query-after-deleting-an-entity-that-is-used-in-a-union-type/15483&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://discuss.dgraph.io/t/bug-cannot-limit-number-of-results-using-auth-directive-to-prevent-malicious-queries/14828/5" rel="noopener noreferrer"&gt;https://discuss.dgraph.io/t/bug-cannot-limit-number-of-results-using-auth-directive-to-prevent-malicious-queries/14828/5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In the end Kudos to Teammates who made this migration possible!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brightsec.com/blog/graphql-security/" rel="noopener noreferrer"&gt;GraphQL Security: The complete guide&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Level Up Coding
&lt;/h3&gt;

&lt;p&gt;Thanks for being a part of our community! Before you go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👏 Clap for the story and follow the author 👉&lt;/li&gt;
&lt;li&gt;📰 View more content in the &lt;a href="https://levelup.gitconnected.com/?utm_source=pub&amp;amp;utm_medium=post" rel="noopener noreferrer"&gt;Level Up Coding publication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💰 Free coding interview course ⇒ &lt;a href="https://skilled.dev/?utm_source=luc&amp;amp;utm_medium=article" rel="noopener noreferrer"&gt;View Course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔔 Follow us: &lt;a href="https://twitter.com/gitconnected" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/company/gitconnected" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://newsletter.levelup.dev" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀👉 &lt;a href="https://jobs.levelup.dev/talent/welcome?referral=true" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Level Up talent collective and find an amazing job&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>bigbangmigration</category>
      <category>prisma</category>
      <category>node</category>
      <category>java</category>
    </item>
    <item>
      <title>How to Prevent No-SQL Injection in Node.js</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Thu, 20 Apr 2023 16:32:14 +0000</pubDate>
      <link>https://forem.com/pshaddel/how-to-prevent-no-sql-injection-in-nodejs-59k2</link>
      <guid>https://forem.com/pshaddel/how-to-prevent-no-sql-injection-in-nodejs-59k2</guid>
      <description>&lt;p&gt;This article explains what is No-SQL Injection attack, how usually attackers make it and, how we can prevent it.&lt;/p&gt;

&lt;p&gt;The attack is called SQL Injection but the same concept applies to No-SQL databases too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsk8xf8b5ud922arz0uh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsk8xf8b5ud922arz0uh.png" width="800" height="772"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;SQL or No-SQL Injection&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why it is important to know (No-)SQL Injection?
&lt;/h3&gt;

&lt;p&gt;By taking a look at &lt;a href="https://www.hackerone.com/top-ten-vulnerabilities" rel="noopener noreferrer"&gt;HackerOne Top Ten Vulnerabilities&lt;/a&gt; we can quickly understand the importance of SQL Injection and why we should care about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrk5euqdjkoz3se1wukw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrk5euqdjkoz3se1wukw.png" alt="SQL Injection Rank in HackerOne Bonty(Rank 7th)" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;SQL Injection Bounty ranking&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are two main reasons that make (No-)SQL Injection very tempting for attackers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Abundance of (No-)SQL Injection vulnerabilities&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Database is a very attractive target since it contains critical data&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  What is a (No-)SQL Injection?
&lt;/h3&gt;

&lt;p&gt;What we do on the backend side is mostly based on the data that comes from the request(user). An example is when a user does Login. So we have to get the email of the user and check if it exists and matches the password. We store data in the database and as a result, we have to make a query to the database to find the email. &lt;strong&gt;So the Email that the &lt;em&gt;User&lt;/em&gt; gave to us is part of the &lt;em&gt;Query&lt;/em&gt;&lt;/strong&gt;. This is where the attacker can do some tricks to extract or manipulate data by giving us something other than a simple Email. This is how an SQL Injection is done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Intention of (No-)SQL Injection is access to the database or parts of the database that it should not have.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples of No-SQL Injection Attacks
&lt;/h3&gt;
&lt;h4&gt;
  
  
  No-SQL Injection(MongoDB)
&lt;/h4&gt;

&lt;p&gt;In the first example, we want to work on Express app that uses &lt;a href="https://github.com/mongodb/node-mongodb-native" rel="noopener noreferrer"&gt;MongoDB Native Driver&lt;/a&gt;. Why anyone might want to use the native driver? Because in terms of performance, it is the best!(As you can see in the chart below)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7le6dv8un1ipqcugvnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7le6dv8un1ipqcugvnl.png" width="800" height="461"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mongoose vs MongoDB Driver&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MongoClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb://localhost:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;raw-mongodb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMongoDBRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;userMongoDBRouter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login successful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;userMongoDBRouter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;hashPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User created&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a login route that does not have &lt;strong&gt;Validation&lt;/strong&gt; and passes email and password directly to MongoDB Driver.&lt;/p&gt;

&lt;p&gt;First, let’s create a user with the register route and check the Login logic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkf3602zhhl4wca7rzh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwkf3602zhhl4wca7rzh3.png" width="800" height="731"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Create a Valid User with Password and Email&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we can login with this valid user that we just created but If we use an invalid user, obviously we cannot Login:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcgsgxlhulmz8xofkgzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcgsgxlhulmz8xofkgzu.png" width="800" height="731"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Failed Login with User: &lt;a href="mailto:Attacker@gmail.com"&gt;Attacker@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to do the No-SQL Injection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We know that MongoDB supports regex with the operator $regex so we can pass this operator instead of a String and use a regex that accepts anything ,*:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$regex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".*"&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$regex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".*"&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the picture we were able to Login without having a user:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu040uez2vgvjhrc4ido9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu040uez2vgvjhrc4ido9.png" width="800" height="709"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Using Regex Operator to Bypass MongoDB findOne&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was done with MongoDB native driver. Using other ODM’s like &lt;a href="https://github.com/Automattic/mongoose" rel="noopener noreferrer"&gt;&lt;strong&gt;Mongoose&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;will not solve this issue:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userMongooseRouter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dbName&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// mongoose enable debug mode&lt;/span&gt;
  &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;debug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;password&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid credentials&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Login successful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mongoose is behaving the way we expect. We can bypass login by using $regex .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4mtngefp3ktbxstihxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4mtngefp3ktbxstihxl.png" width="800" height="714"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Bypassing Login when using Mongoose&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Is it the responsibility of ODM to Prevent (No-)SQL Injections?
&lt;/h4&gt;

&lt;p&gt;I was mad at my ODM(Mongoose) at first but after a little bit of thinking I realized that Mongoose or Prisma are just libraries for easier database interactions. How could they distinguish that it is you that wants to use the regex or an attacker?&lt;/p&gt;

&lt;p&gt;Long story short: &lt;strong&gt;It is not the responsibility of ODM or ORM&lt;/strong&gt; and even if some of them are doing it you cannot be so sure that your app is safe against Injections(&lt;a href="https://security.snyk.io/vuln/SNYK-JS-SEQUELIZE-3324090" rel="noopener noreferrer"&gt;Sequalize Security Issue&lt;/a&gt; that resulted in SQL Injection).&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Prevent No-SQL Injection
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Avoid Passing Request Objects Directly To ODM or ORM Functions
&lt;/h4&gt;

&lt;p&gt;The worst thing we can do is to pass something like req.body or req.query directly to our ODM/ORM functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const user = await collection.findOne(req.body); // Bad Practice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The least we can do is to use the specific fields&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const user = await collection.findOne({ userId: req.body.id });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Use Input Validation
&lt;/h4&gt;

&lt;p&gt;Using something like &lt;a href="https://zod.dev/?id=strings" rel="noopener noreferrer"&gt;Zod&lt;/a&gt;, &lt;a href="https://github.com/jquense/yup" rel="noopener noreferrer"&gt;Yup&lt;/a&gt;, and other options.&lt;/p&gt;

&lt;p&gt;Example of validating with Zod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const loginValidator = z.object({
  email: z.string().email(),
  password: z.string()
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using objectStrict it will return an error if someone tries to add extra fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const loginValidator = z.strictObject({
  email: z.string().email(),
  password: z.string()
});
userMongooseRouter.post("/login", async (req, res) =&amp;gt; {
  const result = loginValidator.safeParse(req.body);
  if (!result.success) {
    res.status(401).send("Invalid credentials");
    return;
  }
  await mongoose.connect(url, { dbName });
  const db = mongoose.connection;
  const collection = db.collection("users");
  // mongoose enable debug mode
  mongoose.set("debug", true);
  const user = await collection.findOne(result.data);
  if (!user) {
    res.status(401).send("Invalid credentials");
    return;
  } else {
    res.json({ message: "Login successful", user: user });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now sending a request like this will result in an error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASZm8ViZAwFh5HxOn1Uwo8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ASZm8ViZAwFh5HxOn1Uwo8Q.png" width="800" height="612"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sending Extra Field in the Body of Request&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Sanitize User Inputs and Filters
&lt;/h4&gt;

&lt;p&gt;Hopefully, Mongoose 6 introduced a &lt;a href="https://mongoosejs.com/docs/api/mongoose.html#Mongoose.prototype.sanitizeFilter()" rel="noopener noreferrer"&gt;sanitizer&lt;/a&gt; that you can use: “Sanitizes query filters against &lt;a href="https://thecodebarbarian.com/2014/09/04/defending-against-query-selector-injection-attacks.html" rel="noopener noreferrer"&gt;query selector injection attacks&lt;/a&gt; by wrapping any nested objects that have a property whose name starts with $ in a $eq.”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const obj = { username: 'val', pwd: { $ne: null } };
sanitizeFilter(obj);
obj; // { username: 'val', pwd: { $eq: { $ne: null } } });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By wrapping phrases in $eq it prevents injections that are trying to get more data.&lt;/p&gt;

&lt;p&gt;If we are not using Mongoose there are other options to consider:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fiznool/express-mongo-sanitize" rel="noopener noreferrer"&gt;express-mongo-sanitize&lt;/a&gt; is a library that checks req.body, req.params, req.query and req.headers for prohibited characters.&lt;/p&gt;

&lt;p&gt;Another option is &lt;a href="https://github.com/vkarpov15/mongo-sanitize" rel="noopener noreferrer"&gt;mongo-sanitize&lt;/a&gt; that strip out any keys which start with $ in the input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;We know that (No-)SQL Injection is important and common since the target is the database. We need to do some simple steps to prevent this attack: 1- Avoid passing req objects directly, use strong validation, and in the end use sanitizers.&lt;/p&gt;

&lt;p&gt;These other articles might be also interesting for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/treyhuffine/prevent-csrf-attacks-in-node-js-application-358b-temp-slug-3843041"&gt;Prevent CSRF Attacks in Node.JS application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/pshaddel/prevent-parameter-pollution-in-nodejs-2ela-temp-slug-4567717"&gt;Prevent Parameter Pollution in Node.JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/treyhuffine/how-to-prevent-ssrf-attacks-in-nodejs-391p-temp-slug-5486096"&gt;How to prevent SSRF attacks in Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/pshaddel/prevent-brute-force-attacks-in-nodejs-1g7b-temp-slug-1083629"&gt;Prevent Brute Force Attacks in Node.JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html" rel="noopener noreferrer"&gt;SQL Injection Prevention - OWASP Cheat Sheet Series&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level Up Coding
&lt;/h3&gt;

&lt;p&gt;Thanks for being a part of our community! Before you go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👏 Clap for the story and follow the author 👉&lt;/li&gt;
&lt;li&gt;📰 View more content in the &lt;a href="https://levelup.gitconnected.com/?utm_source=pub&amp;amp;utm_medium=post" rel="noopener noreferrer"&gt;Level Up Coding publication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💰 Free coding interview course ⇒ &lt;a href="https://skilled.dev/?utm_source=luc&amp;amp;utm_medium=article" rel="noopener noreferrer"&gt;View Course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔔 Follow us: &lt;a href="https://twitter.com/gitconnected" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/company/gitconnected" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://newsletter.levelup.dev" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀👉 &lt;a href="https://jobs.levelup.dev/talent/welcome?referral=true" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Level Up talent collective and find an amazing job&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>security</category>
      <category>node</category>
      <category>express</category>
      <category>nosqlinjection</category>
    </item>
    <item>
      <title>How to prevent SSRF attacks in Node.js</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Mon, 10 Apr 2023 00:43:28 +0000</pubDate>
      <link>https://forem.com/pshaddel/how-to-prevent-ssrf-attacks-in-nodejs-29od</link>
      <guid>https://forem.com/pshaddel/how-to-prevent-ssrf-attacks-in-nodejs-29od</guid>
      <description>&lt;p&gt;This articles explains what is SSRF attack, how usually attackers make it and how we can prevent it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it is important to know SSRF?
&lt;/h3&gt;

&lt;p&gt;By taking a look at &lt;a href="https://www.hackerone.com/top-ten-vulnerabilities" rel="noopener noreferrer"&gt;HackerOne Top Ten Volunuriblities&lt;/a&gt; we can quickly understand the importance of SSRF and why me and you as developers should care about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rkc5fk67q5t9fg0ph0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rkc5fk67q5t9fg0ph0q.png" alt="A Table shows that SSRF is the fourth common bounty" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;HackerOne Bounty Table By Type&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a SSRF Attack?
&lt;/h3&gt;

&lt;p&gt;SSRF is the abbreviation for &lt;strong&gt;&lt;em&gt;Server Side Request Forgery&lt;/em&gt;&lt;/strong&gt;. Let’s explain it with an &lt;em&gt;example&lt;/em&gt; instead of classic definitions. Imagine that you have a application, and your users need profile picture. Suddenly you decide that just uploading the picture is not enough for my users should be able to &lt;strong&gt;pass a URL,&lt;/strong&gt; and I will download the picture and use it as their avatar. The problem begins in here. &lt;strong&gt;Downloading the picture means a GET request to a server that we do not have that much information about&lt;/strong&gt;. Now that the attacker nows that you are making these GET requests he passes a URL like this to you: &lt;a href="http://localhost/admin" rel="noopener noreferrer"&gt;&lt;strong&gt;http://localhost/admin&lt;/strong&gt;&lt;/a&gt; . If your system did not consider this attack you will send a GET request to your host admin which is definitely dangerous when someone can somehow &lt;strong&gt;interact&lt;/strong&gt; with your &lt;strong&gt;Internal Systems or Services&lt;/strong&gt;. Now if you are showing the result of the image download request it could make it much easier for attacker to explore your internal services and do something. I should mention that this type of attack is not limited to Internal Services and it could affect also &lt;strong&gt;External Systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The intention of the SSRF Attack is usually to &lt;strong&gt;exploit trust relationships to escalate an attack from the vulnerable application and perform unauthorized actions.&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Different Types of SSRF Attacks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server Attacks&lt;/strong&gt; : In the example of downloading user Avatar from a URL if we pass something like localhost or 127.0.0.1 or the IP of the server we are attacking the server itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal Backend Systems&lt;/strong&gt; : In this case attacker tries to communicate with other backend systems and for doing that he uses URL’s that contain private network IPs like &lt;a href="http://192.168.0.68/admin" rel="noopener noreferrer"&gt;http://192.168.0.68/admin&lt;/a&gt; or even using names like &lt;a href="https://payment/something" rel="noopener noreferrer"&gt;https://payment/something&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External Systems&lt;/strong&gt; : This could be an external system that only your server or service is able to interact. This could be a bank API or anything that is restricted their service to your IP address with some other forms of authentication and authorization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0mzwpxdxrq0t8n95tx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0mzwpxdxrq0t8n95tx2.png" width="793" height="339"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Schema of a SSRF attack in attempt to get access to 10.0.0.1&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  What is Basic SSRF and Blind SSRF?
&lt;/h4&gt;

&lt;p&gt;In the example of downloading user picture from a URL if we return the response directly to the user, then the attacker is able to see the response and explore our services much faster. If we do not show any response from the request then the attack type becomes blind SSRF which becomes harder for the attacker to explore our systems without seeing the response.&lt;/p&gt;
&lt;h3&gt;
  
  
  An Example of a SSRF Attack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What This Service Is Doing&lt;/strong&gt; : It is a resume builder website and when you are filling a field for your personal website it checks if it is a valid website or not and gives you a feedback to fix your URL if it cannot &lt;strong&gt;make a request to it!&lt;/strong&gt; This application has a base part which has routes and you have to authenticate yourself to access these routes. We have a &lt;strong&gt;internal service&lt;/strong&gt; called &lt;strong&gt;Payment&lt;/strong&gt; that only the main app have access to it and it is not public.(This is full of simplification and the intention is to understand a situation that this could happen).&lt;/p&gt;

&lt;p&gt;Let’s see the main app. It consists of :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;personal-website&lt;/em&gt;: for checking the url and it gives you the message that says success and also returns response that came from your personal website(This is not a common thing to do but we are doing this to not make it a blind attack) to show a preview of the website to you.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;me/balance&lt;/em&gt;: for checking current user’s balance. It makes a request to our payment service.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;me/payin&lt;/em&gt;: for adding money to my wallet. It makes a request to our payment service.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentServiceAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost:3011&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/personal-website&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;websiteHomePageTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveAddressInProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;websiteHomePageTest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isAxiosError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/me/balance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;someAuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paymentServiceAddress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/1/balance`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/me/balance/payin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;someAuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;payIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// now we want to update the balance&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paymentServiceAddress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/1/balance/increase`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening at http://localhost:3010`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveAddressInProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;save the image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;someAuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;payIn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If we use a valid URL for our personal website we get this result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpp9xrfmvhzpnce5rh05z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpp9xrfmvhzpnce5rh05z.png" width="800" height="474"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;HTTP Client that shows the message is success&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At this point we are sure that this app is &lt;strong&gt;making a request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now if we try some other URL’s we can check other services that could be exploit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwlt3xa58l418dzil7x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwlt3xa58l418dzil7x3.png" width="800" height="474"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Using local URL for SSRF&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It gives us information about the &lt;strong&gt;server&lt;/strong&gt; and &lt;strong&gt;internal services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now the attacker should start playing with the URL to find some other services. Finally if we try an address like &lt;a href="http://localhost:3011" rel="noopener noreferrer"&gt;http://localhost:3011&lt;/a&gt; we see that the result becomes success and it means that there is a service behind this URL. Let’s see the implementation of payment service. We cannot make direct requests to this service since it is in a private network but we can make requests from the main app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:userId/balance&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getUserBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3011&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening at http://localhost:3011`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a little bit of trying the attacker could find that there is a route that gives balance to the user.(when the URL is not correct the payment service returns 404 and we see the result in the response).&lt;/p&gt;

&lt;p&gt;By using the balance route which is a GET request we can access all users balance by using their userId. Normally by using this route on main app /me/balance we were able to see our own balance but now we have unauthorized access to other users’ balance too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpducqlyng3q3i581mdtm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpducqlyng3q3i581mdtm.png" width="800" height="517"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Unauthorized Access to Users’ Balance&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Prevent SSRF Attacks
&lt;/h3&gt;

&lt;p&gt;Now it is time to think about solution and prevent this attack step by step.&lt;/p&gt;

&lt;h4&gt;
  
  
  1- Validation
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Black List&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use Regex for validating the URL or having a black list of forbidden phrases like 127.0.0.1 or localhost. You can use regex directly or you can use validators like &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; ,&lt;a href="https://github.com/hapijs/joi" rel="noopener noreferrer"&gt;hapi&lt;/a&gt; , &lt;a href="https://github.com/validatorjs/validator.js" rel="noopener noreferrer"&gt;validatorjs&lt;/a&gt; and so many other options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IP Address&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are accepting &lt;strong&gt;IP addresses&lt;/strong&gt; or if you have a whitelist or black list that you want to check against, you can use this library for that: &lt;a href="http://ip-address.js.org/" rel="noopener noreferrer"&gt;ip-address&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are only accepting &lt;strong&gt;Domain&lt;/strong&gt; names then this library could be helpful: &lt;a href="https://github.com/miguelmota/is-valid-domain" rel="noopener noreferrer"&gt;is-valid-domain&lt;/a&gt;. It is archived but it does not have any dependency to other projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Be aware of the problem that there are so many ways to bypass the validation. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using an alternative IP representation of 127.0.0.1, such as 2130706433, 017700000001, or 127.1.&lt;/li&gt;
&lt;li&gt;Registering your own domain name that resolves to 127.0.0.1. You can use spoofed.burpcollaborator.net for this purpose.&lt;/li&gt;
&lt;li&gt;Obfuscating blocked strings using URL encoding or case variation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So this input validation is just the beginning.&lt;/p&gt;

&lt;h4&gt;
  
  
  2- Network Layer
&lt;/h4&gt;

&lt;p&gt;If a service does not interact with another service it should not have access to that service in internal private network. Since we are working with docker and k8s a lot this might happen that two pod or container do not have any relation but they can make requests to each other. This could be a potential issue. If a pod is using another pod called database and other pods do not need this database then these other pods should not be able to make requests to this pod(&lt;a href="https://learn.microsoft.com/en-us/azure/aks/use-network-policies" rel="noopener noreferrer"&gt;Azure Example&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  3- Use SSRF Agents
&lt;/h4&gt;

&lt;p&gt;By using Nodejs libraries like &lt;a href="https://github.com/y-mehta/ssrf-req-filter" rel="noopener noreferrer"&gt;ssrf-req-filter&lt;/a&gt; or &lt;a href="https://github.com/welefen/ssrf-agent" rel="noopener noreferrer"&gt;ssrf-agent&lt;/a&gt; you can prevent passing private URL’s to your app.&lt;/p&gt;

&lt;h4&gt;
  
  
  4- Use Proper Authentication and Authorization
&lt;/h4&gt;

&lt;p&gt;In our example we saw that the main application had access to make any kind of requests to payment service. A better approach could be to pass in the user authentication information(it might be a JWT or session or anything) and then payment gets the userId from JWT payload and then we are sure that this user has access to this data. Even backend services should have limited access on each other. If they rely on user access then it could be harder to get unauthorized access.&lt;/p&gt;

&lt;h4&gt;
  
  
  5- Do Not Expose Response of Unknown Requests
&lt;/h4&gt;

&lt;p&gt;Another mistake in the example was that it was exposing a http request response both in success and failure mode. Any extra information could be a potential clue for the attacker. So when the personal website is not available or gives internal server we should not care. We should always return something similar, for example a bad request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Overall making a request based on client url is a risk and by doing validation, checking that it is not a private IP address or not and testing against some black list phrases we can reduce the risk. Best thing to do is to have a concrete authentication authorization system that could stay resilient even when the systems are making requests that they should’t.&lt;/p&gt;

&lt;p&gt;Thanks for reading this article.&lt;br&gt;&lt;br&gt;
In case you like it you can check my previous articles about security in Nodejs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/gitconnected/prevent-brute-force-attacks-in-node-js-419367ae35e6?source=your_stories_page-------------------------------------" rel="noopener noreferrer"&gt;How to Prevent Brute Force Attack in Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/gitconnected/prevent-csrf-attacks-in-node-js-application-d71df3704944?source=your_stories_page-------------------------------------" rel="noopener noreferrer"&gt;How to Prevent CSRF Attacks in Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/gitconnected/prevent-parameter-pollution-in-node-js-f0794b4650d2?source=your_stories_page-------------------------------------" rel="noopener noreferrer"&gt;How to Prevent Parameter Pollution in Node.js&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://sethsec.blogspot.com/2015/12/exploiting-server-side-request-forgery.html" rel="noopener noreferrer"&gt;Exploiting Server Side Request Forgery on a Node/Express Application (hosted on Amazon EC2)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/sethsec/Nodejs-SSRF-App" rel="noopener noreferrer"&gt;GitHub - sethsec/Nodejs-SSRF-App: Nodejs application intentionally vulnerable to SSRF&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/y-mehta/ssrf-req-filter" rel="noopener noreferrer"&gt;GitHub - y-mehta/ssrf-req-filter: Module to prevent SSRF when sending requests in NodeJS. Blocks request to local and private IP addresses&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://portswigger.net/web-security/ssrf" rel="noopener noreferrer"&gt;What is SSRF (Server-side request forgery)? Tutorial &amp;amp; Examples | Web Security Academy&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level Up Coding
&lt;/h3&gt;

&lt;p&gt;Thanks for being a part of our community! Before you go:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👏 Clap for the story and follow the author 👉&lt;/li&gt;
&lt;li&gt;📰 View more content in the &lt;a href="https://levelup.gitconnected.com/?utm_source=pub&amp;amp;utm_medium=post" rel="noopener noreferrer"&gt;Level Up Coding publication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💰 Free coding interview course ⇒ &lt;a href="https://skilled.dev/?utm_source=luc&amp;amp;utm_medium=article" rel="noopener noreferrer"&gt;View Course&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔔 Follow us: &lt;a href="https://twitter.com/gitconnected" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://www.linkedin.com/company/gitconnected" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | &lt;a href="https://newsletter.levelup.dev" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀👉 &lt;a href="https://jobs.levelup.dev/talent/welcome?referral=true" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Level Up talent collective and find an amazing job&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>node</category>
      <category>security</category>
      <category>ssrf</category>
    </item>
    <item>
      <title>Boost Your Productivity: Simple Tips for Developers</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Mon, 13 Mar 2023 02:26:45 +0000</pubDate>
      <link>https://forem.com/pshaddel/boost-your-productivity-simple-tips-for-developers-576o</link>
      <guid>https://forem.com/pshaddel/boost-your-productivity-simple-tips-for-developers-576o</guid>
      <description>&lt;p&gt;&lt;a href="https://levelup.gitconnected.com/boost-your-productivity-simple-tips-for-developers-448724cb1d9c?source=rss-8f1fd23dbcf6------2" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvrd5yp5uu9g3w2f3f75.jpeg" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article provides useful tips for maintaining productivity during development work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://levelup.gitconnected.com/boost-your-productivity-simple-tips-for-developers-448724cb1d9c?source=rss-8f1fd23dbcf6------2" rel="noopener noreferrer"&gt;Continue reading on Level Up Coding »&lt;/a&gt;&lt;/p&gt;

</description>
      <category>focus</category>
      <category>pomodoro</category>
      <category>boost</category>
      <category>developer</category>
    </item>
    <item>
      <title>Build your First Node.js Web Framework Step by Step</title>
      <dc:creator>Poorshad Shaddel</dc:creator>
      <pubDate>Mon, 02 Jan 2023 01:27:22 +0000</pubDate>
      <link>https://forem.com/pshaddel/build-your-first-nodejs-web-framework-step-by-step-3k0e</link>
      <guid>https://forem.com/pshaddel/build-your-first-nodejs-web-framework-step-by-step-3k0e</guid>
      <description>&lt;p&gt;We want to create a super simple web framework in order to get an idea of how web framework libraries are working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yjyptrvz42fnmiiy3o2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yjyptrvz42fnmiiy3o2.png" width="800" height="443"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Build Your First Node.js Web Framework&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the previous &lt;a href="https://p-shaddel.medium.com/expressjs-deep-dive-387f07c50d95?source=user_profile---------0----------------------------" rel="noopener noreferrer"&gt;article&lt;/a&gt;, we took a look at &lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;Expressjs&lt;/a&gt; and tried to understand how this library works. In this article, we want to build something super simple in order to feel the challenges and feel comfortable when we want to take a look at the source code of other libraries.&lt;/p&gt;

&lt;p&gt;Let’s get to coding without hesitation.&lt;/p&gt;
&lt;h4&gt;
  
  
  Handle Requests using Node.js HTTP Library
&lt;/h4&gt;

&lt;p&gt;We are going to use the Node.js HTTP library which is one of the core libraries and you do not need to install anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we send a request to any route in localhost:8000/anything/you/want we get pong as a result. Now let’s implement our features.&lt;/p&gt;

&lt;h4&gt;
  
  
  Our Strategy for Handling Requests
&lt;/h4&gt;

&lt;p&gt;For handling a request in a normal application most of the time we are doing &lt;em&gt;totally different operations&lt;/em&gt; on the same incoming request. As an example, a request wants to update a user. And imagine this is how the request looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Method: POST
URL: "http://ourAddress/users/userId"
JSON Body of request: { name: "something New" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a backend service I want to do different operations on this request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;Parse Body of the request&lt;/li&gt;
&lt;li&gt;Log the operation and the person who did the operation&lt;/li&gt;
&lt;li&gt;Update the User in the Database
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;myHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Authorization&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAuthorizedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;authorizeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthorizedUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// return some bad error&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Parse Body of the Request&lt;/span&gt;
    &lt;span class="nf"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Log the error&lt;/span&gt;
    &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="c1"&gt;// Update the user&lt;/span&gt;
    &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is totally OK. But imagine there are more than twenty different routes in the same application and all of them need almost the same operations. All of them need to log every action or authorize the request. So we need a way to reduce code duplications. One common strategy for solving this issue is the concept of &lt;strong&gt;middleware&lt;/strong&gt;. ExpressJS uses this concept and we also want to implement something like this.&lt;/p&gt;

&lt;p&gt;Now look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;authorizationMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAuthorizedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;authorizeRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthorizedUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// return some bad error&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
            &lt;span class="c1"&gt;// How to tell next functions that we already send the request to the user?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// What to do? should go to the next function&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bodyParserMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;authorizationMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;bodyParserMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we only have one route in our application and it updates the user.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Do You Need a Next Function?
&lt;/h4&gt;

&lt;p&gt;There is a big difference between authorizationMiddleware and the other ones, if the user is unauthorized we are returning the response to the user and it does not make sense to send the request to other handlers like body-parser, logger, or update user. &lt;strong&gt;So we need a mechanism for knowing when the request is sent and we should stop handing over the request and response object to the middlewares.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For doing this the first thing we need to do is to store these middlewares somewhere. Then we can implement the &lt;em&gt;next function&lt;/em&gt; to pass the request to these middlewares. At the same time, we can solve the problem of having different handlers for different functions.&lt;/p&gt;

&lt;p&gt;In Expressjs they keep middlewares(handler functions) in an array. Let’s do it kind of the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FastFramework&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// An array for keeping the middlewares&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Next Function While Loop- Current Counter:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// If we are here then no middleware matched!!!!&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// A method that we can add middelwares&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;handler&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// if the request is a match for the middleware or not&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FastFramework&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function FastFrameWork is just for returning the HTTP instance.&lt;/p&gt;

&lt;p&gt;In line 5 we see an array for keeping all the middlewares. After creating an HTTP server we defined a variable for keeping track of the current middleware that should be handled.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next Function
&lt;/h4&gt;

&lt;p&gt;In line 8 we implemented the nextFunction and later on, we called this function so it can start processing the request and response, and we intentionally put the variable middlewareCounter outside the next function. In line 10 we have a while loop, it loops over middlewares until it finds a match.&lt;/p&gt;

&lt;p&gt;If it is a match in line 12 we are calling the handler function of the middleware. The most important thing happens here:&lt;/p&gt;

&lt;p&gt;return middlewares[middlewareCounter++].handler(req, res, nextFunction)&lt;br&gt;&lt;br&gt;
We are also passing the next function as an argument to the handler, so we can use this argument to call this function and let other middlewares handle the request. If we are sending the response in the implementation of our middleware handlers and we are not calling the next function which means that this is the last stop for the request. If do not call the next function and we do not return any response then the request will timeout after a while. Also, we are increasing the counter variable because we want the next middleware next time we are in this piece of code.&lt;/p&gt;

&lt;p&gt;If it was not a match in line 14 we just increase the variable so the while loop will check the next middleware or if it was the last middleware it gets out of the loop and it does nothing.&lt;/p&gt;
&lt;h4&gt;
  
  
  Use Function
&lt;/h4&gt;

&lt;p&gt;Like Express I named it use method. This function just adds the middleware to the array of middlewares. The arguments are url , method and handler should be a function like this: (req, res, next) =&amp;gt; {...} .&lt;/p&gt;
&lt;h4&gt;
  
  
  Match Function
&lt;/h4&gt;

&lt;p&gt;Now let’s implement something for this match function. We can check if the method and URL are the same or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know that right now it cannot handle URL patterns like this:&lt;/p&gt;

&lt;p&gt;/api/users/:id but that is OK.&lt;/p&gt;

&lt;h4&gt;
  
  
  Usage
&lt;/h4&gt;

&lt;p&gt;We can import this library like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FastFramework&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./lib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastFramework&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authrized the user...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;logged the user...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prepating the list of users...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some users...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/otherRoute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;other route&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;other info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we send a request we must see some users...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28huhr87xcm5q0do72kp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28huhr87xcm5q0do72kp.png" width="800" height="59"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Response to the request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We expect to see logs of all the routes in order except the /otherRoute which does not match the request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4h6l70b0uidx9au6xtm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4h6l70b0uidx9au6xtm.png" width="800" height="138"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Log of response to the request: GET /users&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As expected first middleware that is handled is the authorization, then the log, and finally the users.&lt;/p&gt;

&lt;p&gt;Now if we send a request to /otherRoute we should only see the log of otherRoute:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy2w0c0ru1o1e5vx02e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy2w0c0ru1o1e5vx02e2.png" width="800" height="100"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Log of the request to otherRoute&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  How to Handle 404
&lt;/h4&gt;

&lt;p&gt;For handling not found requests we need a middleware that matches every request. And we put this middleware as the last middleware so if we know that this request did not match with any of the middlewares. Let’s do this small change to our framework. It is just your choice how you want to implement this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we do not pass URL and Method to the use function it returns true which means that it going to be a match.&lt;/p&gt;

&lt;p&gt;Let’s add our &lt;em&gt;not found middleware&lt;/em&gt; as the last middleware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NOT_FOUND&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we send a request to an unknown URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ce6keeaq4eav6v7vjea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ce6keeaq4eav6v7vjea.png" width="800" height="80"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Request to a route that does not exist&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Implement res.json Method
&lt;/h4&gt;

&lt;p&gt;We need to add this code after creating the server(where we have the request and response):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our FastFramework function looks like this after this change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FastFramework&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// An array for keeping the middlewares&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Next Function While Loop- Current Counter:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;middlewareCounter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// If we are here then no middleware matched!!!!&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;nextFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;// A method that we can add middelwares&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;handler&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s use this function in a simple middleware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prepating the list of users...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxqw2mnwpfs0jzr0iis6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxqw2mnwpfs0jzr0iis6.png" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Body Parser
&lt;/h4&gt;

&lt;p&gt;We can use the body-parser library under the Expressjs project:&lt;/p&gt;

&lt;p&gt;npm i body-parser&lt;/p&gt;

&lt;p&gt;It is usable because our Framework also has the next function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastFramework&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we did not pass a URL or method body parser will be used for every request after this middleware.&lt;/p&gt;

&lt;p&gt;Let’s see the request body before and after using body-parser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { FastFramework } = require("./lib");
const bodyParser = require('body-parser');

const app = FastFramework();

app.use('/user', 'POST', (req, res, next) =&amp;gt; {
    console.log("body before:", req.body);
    next();
});

app.use(null, null, bodyParser.json());

app.use('/user', 'POST', (req, res) =&amp;gt; {
    console.log("body after:", req.body);
    res.json({});
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response is as expected an empty object and as we can see in the logs the body of the request is parsed correctly in it is in the req.body&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgcqsdvzq7djzxkp61f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgcqsdvzq7djzxkp61f3.png" width="800" height="115"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Logs of request body before and after using body parser.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;As you saw the most difficult thing was to add a concept like middleware for reusing the logic. For that, we implemented the &lt;strong&gt;&lt;em&gt;next function&lt;/em&gt;&lt;/strong&gt; and we were able to handle requests and pass the request and response objects between these middlewares. Feel free to add more functionality to your own HTTP Library.&lt;/p&gt;




</description>
      <category>express</category>
      <category>webframework</category>
      <category>node</category>
    </item>
  </channel>
</rss>
