<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vishw Patel</title>
    <description>The latest articles on DEV Community by Vishw Patel (@vizzv).</description>
    <link>https://dev.to/vizzv</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%2F2396569%2Fce51a5b0-51ba-40b2-8aab-a3eb1f7ebd52.png</url>
      <title>DEV Community: Vishw Patel</title>
      <link>https://dev.to/vizzv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vizzv"/>
    <language>en</language>
    <item>
      <title>99% of developers Don't Get Sockets</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Mon, 28 Apr 2025 16:21:57 +0000</pubDate>
      <link>https://dev.to/vizzv/99-of-developers-dont-get-sockets-4mni</link>
      <guid>https://dev.to/vizzv/99-of-developers-dont-get-sockets-4mni</guid>
      <description>&lt;p&gt;99% of developers don't get sockets.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually is a socket?
&lt;/h2&gt;

&lt;p&gt;You've probably seen electrical sockets, but I'm referring to a completely different kind of socket in the software industry or computer science universe.&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%2Fwcb70uxk3g0usa6emzqc.jpg" 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%2Fwcb70uxk3g0usa6emzqc.jpg" alt="Electrical Sockets" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some ideas, such as sockets, anonymous pipes, file descriptors, etc., are just not adequately represented by us. Most developers' conceptions of these ideas end up being vague, wavy creations. Additionally, there are numerous other ideas and phrases that require attention and are not presented in nearly enough detail. I will thus give you a brief overview of sockets and explain what you need to know about them in this post. So, the next time someone asks you these questions, could you tell me what a socket is, how TCP or UDP uses sockets, and which OSI model layer sockets work in? You won't be at a loss for ideas.&lt;/p&gt;

&lt;p&gt;It is always best to begin with a specific response to the query, "What are sockets?" Essentially, sockets are an abstraction that &lt;code&gt;operating systems&lt;/code&gt; give to allow for communication between several processes on the same machine or over a network. In a two-way communication channel, they serve as endpoints. Therefore, each side of a connection will construct a &lt;strong&gt;socket&lt;/strong&gt; when two machines or two apps need to communicate with one another via the internet or a local network. Additionally, a "socket" is basically a software construct that encapsulates a combination of an IP address, a port number, and a protocol, such as TCP or UDP. This combination is used by the operating system to properly route messages. It can be compared to a telephone.&lt;/p&gt;

&lt;p&gt;The IP address and port are like the phone number and extension, while a socket represents the phone. To create a connection, the two sides need to dial each other appropriately. Maybe you've heard of the &lt;code&gt;OSI model&lt;/code&gt;, but you're wondering how sockets fit into it. The OSI model, a conceptual framework for network system communication, is where sockets should be placed in order to comprehend them in context.&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%2Fqpsmphf1bkvc5ynyri95.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%2Fqpsmphf1bkvc5ynyri95.png" alt="Socket as phone" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the OSI model, sockets mostly function at the transport layer, often known as layer 4. The socket API is called by the application layer, often known as layer 7, such as your web browser or a back-end service, requesting that it send or receive data. After adding some headers and wrapping the data into TCP or UDP segments, the socket forwards it to the network layer or layer 3, which handles IP routing.&lt;/p&gt;

&lt;p&gt;Thus, sockets hide developers from the intricacies of routing, packet fragmentation, retransmission, etc., and offer a clear interface between application logic and the underlying network stack. Alright, but before you can truly comprehend sockets, you must be aware that there are two primary types of sockets: TCP and UDP.&lt;/p&gt;

&lt;p&gt;Transmission control protocol sockets, or TCP sockets, are connection-oriented and offer dependable, error-checked, and ordered data transfer. A three-way handshake involving the exchange of SIN and ACT packets is carried out to establish the connection before data is delivered. This ensures that both parties are prepared, and TCP is perfect for applications like file transfers, database access, and web browsing since it guarantees that packets will arrive in the correct order and without duplication.&lt;/p&gt;

&lt;p&gt;On the other hand, the user datagram protocol, or UDP, is unreliable and connectionless. Without a handshake, it merely sends datagrams to the target IP and port. Delivery, ordering, and integrity are not guaranteed. But as a result, it's much lighter and faster, which makes it perfect for real-time applications where speed is more important than dependability, like streaming videos.&lt;/p&gt;

&lt;p&gt;Sockets have a defined life cycle on the server side. The first step is to create a listening socket that is connected to a particular IP address and port. This socket waits for incoming client connections rather than communicating directly.&lt;/p&gt;

&lt;p&gt;A new socket instance is created specifically for the client after the server accepts a connection made by the client, and the existing socket keeps listening for more requests. This new socket serves as the conduit for all correspondence with that particular client. And because of this, a server may manage numerous clients at once, each with its own socket.&lt;/p&gt;

&lt;p&gt;Multi-threading or multi-processing, in which every client connection is controlled by a different thread or process, is usually used to handle this in synchronous settings. Although this strategy is simple and effective for a limited number of connections, it is not scalable. Every thread has overhead associated with context switching and memory consumption. Additionally, the performance rapidly deteriorates as the number of concurrent sockets increases because of resource fatigue and contention. Techniques like non-blocking IO or event-driven architectures are used to overcome this issue in high performance systems like message brokers, multiplayer gaming servers, and real-time APIs.&lt;/p&gt;

&lt;p&gt;These methods enable the simultaneous management of thousands of open sockets by a single thread or a small group of threads. System functions like select, pull, or even more scalable options like e-pole on Linux or KQ on BSD or Mac OS are used to do this. These methods alert the application only when certain sockets are prepared for reading or writing.&lt;/p&gt;

&lt;p&gt;By preventing idle waiting or redundant pulling, these event notification systems significantly lower CPU consumption and latency, which is why they are the cornerstone of frameworks like Engine X, Node.js, and Async.io.&lt;/p&gt;

&lt;p&gt;The client establishes a socket and connects to the IP address and port of the server. This starts the three-way handshake if TCP is being used. Like working with a file, the client can write to and read from the socket once it is connected. Sockets can actually be used with standard system calls like read and write since they are regarded as file descriptors on Unix-like platforms. To refresh your memory, a file descriptor is essentially an entry that the operating system creates to represent a file and keep information about it when it is opened. Therefore, there will be ten entries in the kernel for every ten files that are open in your operating system. And these entries are nothing, but simple integers called file descriptions.&lt;/p&gt;

&lt;p&gt;In exactly the same way, an integer is also used to represent opening a network socket. The socket descriptor in this instance. In order to free up system resources and stop memory leaks, both the client and the server are expected to shut the socket after the conversation is over. Resource fatigue may result from any incorrectly closed sockets, particularly on servers that are busy. Interesting peculiarities pertaining to socket internals and states are also present. As a result, the system keeps a state machine for every connection to TCP sockets.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LISTEN&lt;/code&gt;, &lt;code&gt;SIN-SENT&lt;/code&gt;, &lt;code&gt;SIN-RECIEVED&lt;/code&gt;, &lt;code&gt;ESTABLISHED&lt;/code&gt;, &lt;code&gt;FIN-WAIT-1&lt;/code&gt;, &lt;code&gt;TIME-WAIT&lt;/code&gt;, and &lt;code&gt;CLOSE-WAIT&lt;/code&gt; are a few of the common states. Additionally, these states correspond to different stages of connection setup, upkeep, and disassembly. To prevent delayed packets from an old connection from being mistakenly regarded as belonging to a new one, the &lt;code&gt;TIME-WAIT&lt;/code&gt; status, for example, is used. Additionally, understanding these stages is essential for detecting problems that frequently afflict servers or high concurrency applications, such as port exhaustion or socket leakage. However, how does the operating system handle socket uniqueness and port numbers in practice?&lt;/p&gt;

&lt;p&gt;A five-tuple consisting of the protocol, source IP, source port, destination IP, and destination port uniquely identifies each socket. Additionally, even when several connections are communicating to the same remote server and port at the same time, this combination enables the OS to discern between them.&lt;/p&gt;

&lt;p&gt;For instance, the OS will allocate a distinct source port to each of the browser tabs connected to example.com:443 so that the client and server can distinguish between those sessions. One machine can have hundreds of open connections to various or even identical distant services thanks to this mechanism. However, network communication is the main topic of socket debates.&lt;/p&gt;

&lt;p&gt;Unix domain sockets, or UDS, are another significant form, such as TCP or UDP over IP. Network sockets are not what these are. On the same host, they are employed for inter-process communication, or IPC. Thus, UDS employs a file path on the file system in place of an IP address and port. For instance, the address might be &lt;code&gt;/temp/app.sock&lt;/code&gt;. Since they completely avoid the network stack and don't require any IP routing or protocol overhead, they are significantly faster than network sockets.&lt;/p&gt;

&lt;p&gt;When efficiency and security are crucial, UDS is frequently used by default for local client-server communication in programs like Postgres SQL and Redis, which you are most likely already familiar with. However, it's crucial to remember that sockets are by nature unsafe. And the reason for this is that, unless specifically encrypted, they send raw data. TLS, or transport layer security, is typically used to provide secure socket connection. An existing socket connection is wrapped with TLS, which guarantees that any data transmitted over it is encrypted and verified. For instance, the SSL module in Python offers the ability to encapsulate a plain socket in TLS. For apps that send sensitive data, such as passwords, financial transactions, private user information, etc., this is crucial.&lt;/p&gt;

&lt;p&gt;Man-in-the-middle attacks and packet sniffing can target any unconfigured or raw sockets that do not employ TLS. There is socket-based connectivity everywhere. Popular protocols for service-to-service communication include gRPC over HTTP2, which is likewise TCP based, and restful APIs over HTTP, which employ TCP sockets. Socket level routing and traffic shaping are controlled by service meshes like ISTTO and load balancers like EngineX or Envoy. For ultra-low latency communication, engineers occasionally construct proprietary binary protocols over raw TCP or UDP connections in high performance systems. Sockets behind the hood are used by technologies such as CFKA, Redis, and Cassandra to distribute data among nodes.&lt;/p&gt;

&lt;p&gt;You should at least be able to explain what a socket is for a very good reason. In actuality, sockets constitute the cornerstone of contemporary work computers. Sockets are used to communicate data across the wire whenever you send an email, stream a video, view a web page, or use a mobile application.&lt;/p&gt;

&lt;p&gt;Gaining a thorough understanding of socket operation as a developer allows you to manage the security and performance of network connection. It also lets you optimize communication protocols, solve complicated problems, and create scalable back-end systems. You will be much more successful if you have a firm understanding of sockets. if this article taught you something new. Post a remark and a like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep learning and keep growing.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>socket</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Mastering Authentication in MERN Stack Apps with JWT</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Thu, 24 Apr 2025 15:50:52 +0000</pubDate>
      <link>https://dev.to/vizzv/mastering-authentication-in-mern-stack-apps-with-jwt-3cki</link>
      <guid>https://dev.to/vizzv/mastering-authentication-in-mern-stack-apps-with-jwt-3cki</guid>
      <description>&lt;h2&gt;
  
  
  Mastering Authentication in MERN Stack Apps with JWT
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will focus on implementing &lt;strong&gt;JWT Authentication&lt;/strong&gt; in a MERN stack application. JWT is a popular and efficient way to handle user authentication in modern web apps. By the end of this tutorial, you will be able to set up user registration, login, and secure routes using JWT.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JWT?
&lt;/h2&gt;

&lt;p&gt;JWT (JSON Web Token) is an open standard (RFC 7519) that defines a compact and self-contained way to securely transmit information between parties as a JSON object. This information stored as JWT is digitally signed. That means information can be verified that it is not tempered and from original source. Because of JWT is self-signatured, this token is widely used for authentication and information exchange in web applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Using JWT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stateless Authentication&lt;/strong&gt;: JWT is stateless, meaning you don’t need to store session information on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt;: JWT tokens can be signed and optionally encrypted, providing security and integrity of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt;: Since JWT is stateless, it is ideal for scaling applications across multiple servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How JWT Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client Logs In&lt;/strong&gt;: The user provides their credentials (username and password) to the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Validates Credentials&lt;/strong&gt;: The server validates the credentials against the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT Creation&lt;/strong&gt;: If the credentials are correct, the server generates a JWT token that contains user information (typically, user ID and other claims).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Receives Token&lt;/strong&gt;: The client stores the token (usually in local storage or cookies) and includes it in the Authorization header of future requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token Validation&lt;/strong&gt;: On every API call, the server validates the token to check if the user is authenticated.&lt;/li&gt;
&lt;/ol&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%2F7hamo0ecb5qfs75yelkl.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%2F7hamo0ecb5qfs75yelkl.png" alt="JWT Token working diagram" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;To get started, let's create a basic MERN stack application with &lt;strong&gt;MongoDB&lt;/strong&gt;, &lt;strong&gt;Express.js&lt;/strong&gt;, &lt;strong&gt;React.js&lt;/strong&gt;, and &lt;strong&gt;Node.js&lt;/strong&gt;. This will include user registration and login functionality.&lt;/p&gt;

&lt;p&gt;First, initialize the Node.js app:&lt;/p&gt;

&lt;p&gt;We can initialize node application using &lt;code&gt;npm init&lt;/code&gt; and it initializes a project by generating a &lt;code&gt;package.json&lt;/code&gt; file, which contains metadata about the project, such as its name, version, description, main file, scripts, author, license, and dependencies.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;npm init&lt;/code&gt; in a terminal, it prompts you with a series of questions to gather information about your project. You can either provide specific answers or press enter to accept the default values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;mern-jwt-auth
&lt;span class="nb"&gt;cd &lt;/span&gt;mern-jwt-auth
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After initializing project, we need to add some dependencies which we will use on our example. We are using &lt;code&gt;express&lt;/code&gt; for server, &lt;code&gt;mongoose&lt;/code&gt; as ODM (Object Data Modeling) library for MongoDB, &lt;code&gt;jsonwebtoken&lt;/code&gt; for generating and verifying JWT tokens, &lt;code&gt;bcryptjs&lt;/code&gt; for encryption, &lt;code&gt;dotenv&lt;/code&gt; for accessing environment variables.&lt;/p&gt;

&lt;p&gt;Install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express mongoose jsonwebtoken bcryptjs dotenv cors
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: We are adding &lt;code&gt;nodemon&lt;/code&gt; as dev dependency, So , we do noyt have to re-run our server every time when we changes something. It will be automatically handled by nodemon.&lt;/p&gt;

&lt;p&gt;Set up your backend structure like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend/
  ├── config/
  ├── controllers/
  ├── middleware/
  ├── models/
  ├── routes/
  └── server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is self-explanatory that all controllers are in controllers folder/directory, middleware are in middleware folder/directory and so on for models and routes also.&lt;/p&gt;

&lt;p&gt;Let's start creating our first model using mongoose. Models are nothing but logical structure of database schema/structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the User Model
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;models&lt;/code&gt; folder, create a &lt;code&gt;User.js&lt;/code&gt; file with the following code to define the User schema:&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&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;bcryptjs&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;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;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="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="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;unique&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="na"&gt;password&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="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Hash the password before saving to the database&lt;/span&gt;
&lt;span class="nx"&gt;userSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pre&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&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="nf"&gt;function &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="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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isModified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&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="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&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;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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="mi"&gt;10&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="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="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;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userSchema&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="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explaining the Model Structure
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Schema&lt;/strong&gt;: We define the &lt;strong&gt;User schema&lt;/strong&gt; using &lt;strong&gt;Mongoose&lt;/strong&gt;, which allows us to model our MongoDB data. The schema defines the structure of the documents we store in the database. For instance, the &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt; fields are crucial for our authentication process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Email as Unique&lt;/strong&gt;: We ensure the &lt;code&gt;email&lt;/code&gt; field is unique so that no two users can register with the same email address. This is important for preventing conflicts during the authentication process and ensures each user is identified by a unique email.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hashing the Password&lt;/strong&gt;: We use &lt;strong&gt;bcryptjs&lt;/strong&gt; to hash the user's password before saving it to the database. This is done in the &lt;code&gt;pre('save')&lt;/code&gt; hook, which is executed before the user document is saved to the database. &lt;strong&gt;Why Hash?&lt;/strong&gt; Storing passwords as plain text is highly insecure. Hashing ensures that even if the database is compromised, the actual passwords remain unreadable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;this.isModified('password')&lt;/code&gt;?&lt;/strong&gt;: This check ensures that we only hash the password when it is newly created or updated, avoiding unnecessary hashing if the password hasn't changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you are not familiar with mongoose schema you can check it official documentation. Below is working link of its documentation while I am writing this blog.&lt;/p&gt;

&lt;p&gt;Mongoose Documentation : &lt;a href="https://mongoosejs.com/docs/guide.html" rel="noopener noreferrer"&gt;Mongoose Documentation&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Register and Login Routes
&lt;/h2&gt;

&lt;p&gt;Now, let’s set up the registration and login routes. We can consider routes are endpoint of rest api. These routes will handle user registration and authentication. In the &lt;code&gt;routes&lt;/code&gt; folder, create a &lt;code&gt;authRoutes.js&lt;/code&gt; 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="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;bcrypt&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;bcryptjs&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;jwt&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;jsonwebtoken&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="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;../models/User&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Register user&lt;/span&gt;
&lt;span class="nx"&gt;router&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;/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;name&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userExists&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;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;email&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;userExists&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User already exists&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;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;await&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;save&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;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User registered successfully&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;// Login user&lt;/span&gt;
&lt;span class="nx"&gt;router&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;/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="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;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;email&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;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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User does not exist&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;isMatch&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;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&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="nx"&gt;user&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;isMatch&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&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="nx"&gt;token&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="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Steps of JWT authentication
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Register Route&lt;/strong&gt;: First, we check if the user already exists using &lt;code&gt;User.findOne({ email })&lt;/code&gt;. This prevents multiple users from registering with the same email address. If the email already exists, we return an error message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Login Route&lt;/strong&gt;: After validating the email, we use &lt;strong&gt;bcryptjs&lt;/strong&gt; to compare the provided password with the hashed password stored in the database. If the password is incorrect, we return an error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JWT Generation&lt;/strong&gt;: Once the user’s credentials are validated, we create a &lt;strong&gt;JWT token&lt;/strong&gt; using &lt;code&gt;jwt.sign()&lt;/code&gt;. The &lt;code&gt;id&lt;/code&gt; of the user is included in the token's payload, allowing the server to identify the user on subsequent requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why Use JWT?&lt;/strong&gt; JWT allows us to create &lt;strong&gt;stateless sessions&lt;/strong&gt;. Once the user logs in, they receive a token, which can be stored on the client side (usually in local storage or cookies). The server doesn’t need to remember anything about the user between requests, making this approach scalable and efficient.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Middleware for Protecting Routes
&lt;/h2&gt;

&lt;p&gt;Middleware refers to functions that process requests before reaching the route handlers. These functions can modify the request and response objects, end the request-response cycle, or call the next middleware function. Middleware functions are executed in the order they are defined. &lt;/p&gt;

&lt;p&gt;Below image shows how middleware works.&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%2Fgerdog6ogpyr4c03wtn8.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%2Fgerdog6ogpyr4c03wtn8.png" alt="Middleware lifecycle" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now back to our authentication part.&lt;/p&gt;

&lt;p&gt;To protect certain routes and ensure only authenticated users can access them, create a &lt;code&gt;authMiddleware.js&lt;/code&gt; file in the &lt;code&gt;middleware&lt;/code&gt; 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&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;jsonwebtoken&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;authMiddleware&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&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="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&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="mi"&gt;1&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;token&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;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;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No token, authorization denied&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;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;400&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;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Token is not valid&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;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="nx"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Middleware?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;authMiddleware&lt;/code&gt;&lt;/strong&gt; function intercepts incoming requests to protected routes, checks for a valid JWT in the &lt;strong&gt;Authorization header&lt;/strong&gt;, and decodes the token to verify the user’s identity. If the token is missing or invalid, the middleware returns an error.&lt;/p&gt;

&lt;p&gt;By using this middleware, we ensure that only authenticated users can access protected routes, like viewing or updating their profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Setup with React
&lt;/h2&gt;

&lt;p&gt;On the frontend, we'll use React to handle user registration and login forms. The &lt;strong&gt;Axios&lt;/strong&gt; library will be used to make API requests to our backend.&lt;/p&gt;

&lt;p&gt;First, install Axios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a &lt;code&gt;login.js&lt;/code&gt; component to handle login and save the token to &lt;code&gt;localStorage&lt;/code&gt;:&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;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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;react&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;axios&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;axios&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;Login&lt;/span&gt; &lt;span class="o"&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="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;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&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="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleLogin&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="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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5000/api/auth/login&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;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="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error logging in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&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;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&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;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&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;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;value&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="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleLogin&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;Login&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;JWT authentication is a simple, effective, and scalable method to handle user authentication in modern web applications. By following this guide, you’ve learned how to implement JWT-based authentication in your MERN stack application. You can expand on this by adding features such as user roles, refresh tokens, and token expiration handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep Learning and keep growing!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>mongodb</category>
      <category>react</category>
    </item>
    <item>
      <title>How to implement Rate limiting in Dot net.</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Wed, 23 Apr 2025 17:35:11 +0000</pubDate>
      <link>https://dev.to/vizzv/how-to-implement-rate-limiting-in-dot-net-web-api-1f8</link>
      <guid>https://dev.to/vizzv/how-to-implement-rate-limiting-in-dot-net-web-api-1f8</guid>
      <description>&lt;p&gt;In this article, we go through on topics listed as what is rate limiting, how to implement it in Dot net with simple approach, problem in simple approach, implement it as production ready solution.&lt;/p&gt;

&lt;p&gt;We are going to address the following topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduction to Rate Limiting&lt;/li&gt;
&lt;li&gt;Project Setup&lt;/li&gt;
&lt;li&gt;Register Redis Connection&lt;/li&gt;
&lt;li&gt;Create Middleware for Rate limiting&lt;/li&gt;
&lt;li&gt;Register middleware&lt;/li&gt;
&lt;li&gt;Run the Application and Check&lt;/li&gt;
&lt;/ol&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%2Fzuqez38rx337c4oa420i.jpg" 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%2Fzuqez38rx337c4oa420i.jpg" alt="Rate Limiting flowchart" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Rate Limiting
&lt;/h2&gt;

&lt;p&gt;Rate limitation refers to a method that limits the quantity of incoming requests that a server receives within a given time frame. The purpose of implementing this is to guarantee the availability, stability, and security of the API. API providers can avoid misuse, lower the chance of server overload, and ensure consistent performance for all users by capping the rate of queries. These are a few important rate-limiting factors.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thresholds&lt;/strong&gt;: Generally, rate restrictions are expressed as the maximum number of requests that are permitted in a given amount of time, &lt;br&gt;
e.g., "100 requests per minute" or "10,000 requests per day."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Identification&lt;/strong&gt;: Different identities, including IP addresses, API keys, user accounts, and other tokens, can be used to apply rate limits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Types of Rate Limiting:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User-based rate limiting&lt;/strong&gt;: This technique applies limits to individual users or accounts so that no user is able to send more requests than is permitted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP-based rate limiting&lt;/strong&gt;: By applying limits according to the IP address of the client, it is possible to keep a single IP from overloading the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application-based rate limiting&lt;/strong&gt;: 
This feature allows you to differentiate between various applications that use the API by enforcing limits depending on the API key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a client exceeds the allowed rate, the server typically responds with an HTTP status code, such as &lt;code&gt;429 Too Many Requests&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The response often includes information about the limit, the time until the limit resets, and guidance on how to retry the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;Create a new ASP.NET Core MVC 7 project or Web Api project, using Visual Studio or VSCode or any text editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new mvc -n RateLimitingDemo
cd RateLimitingDemo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the project, required packages must be downloaded. So, Add following NuGet packages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft.Extensions.Caching.StackExchangeRedis&lt;/li&gt;
&lt;li&gt;StackExchange.Redis
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
dotnet add package StackExchange.Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Register Redis Connection
&lt;/h2&gt;

&lt;p&gt;Before Going any further be sure your redis server is running.&lt;/p&gt;

&lt;p&gt;To start the Redis server, simply run the &lt;code&gt;redis-server&lt;/code&gt; command in your terminal. This will start the server with default configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the server starting up and a log of activities indicating that it is ready to accept connections.&lt;/p&gt;

&lt;p&gt;Open another terminal window to interact with the Redis server using the Redis Command Line Interface (CLI):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;redis-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now check server is responding or not by ping Command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PING &lt;/code&gt;Returns &lt;code&gt;PONG &lt;/code&gt;This command is useful for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Testing whether a connection is still alive.&lt;/li&gt;
&lt;li&gt;Verifying the server's ability to serve data - an error is returned when this isn't the case (e.g., during load from persistence or accessing a stale replica).&lt;/li&gt;
&lt;li&gt;Measuring latency.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If Redis is configured correctly and running fine then we can jump onto next steps:&lt;/p&gt;

&lt;p&gt;Add connection string of Redis in appSettings.json file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Redis": {
    "ConnectionString": "localhost:6379"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Configure Redis in Program.cs&lt;br&gt;
&lt;/p&gt;

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

builder.Services.AddStackExchangeRedisCache(options =&amp;gt;
{
options.Configuration = builder.Configuration.GetSection("Redis"["ConnectionString"];});
//...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Middleware for Rate limiting
&lt;/h2&gt;

&lt;p&gt;Right Click on your Project RateLimitingDemo and click on Add and then Add Folder.Rename that newly created folder from NewFolder to Middlewares.&lt;/p&gt;

&lt;p&gt;After renaming right click on middlewares folder and add New Item, set its name as RateLimitingMiddleware.&lt;/p&gt;

&lt;p&gt;Every middleware in dotnet has &lt;code&gt;Request Delegate&lt;/code&gt; as member and has to implement &lt;code&gt;InvokeAsync&lt;/code&gt;method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class RateLimitingMiddleware
{
 private readonly RequestDelegate _next;
 public RateLimitingMiddleware(RequestDelegate next)
 {
     _next = next;
 }
 public async Task InvokeAsync(HttpContext context)
 {
    // do something 
     await _next(context);
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to add _next() method  , If _next() method is not there then request is not propagating to respective controller and that leads to request being stuck.&lt;/p&gt;

&lt;p&gt;For this case we will do as follow in middleware:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get Ip of request.&lt;/li&gt;
&lt;li&gt;checks Requests ang get Request count from Redis of this Ip.&lt;/li&gt;
&lt;li&gt;if Request count reaches the max limit than we give response 429 too many requests.&lt;/li&gt;
&lt;li&gt;remove Requests than are older than our window size. i.e. time limit.&lt;/li&gt;
&lt;li&gt;Now, Add new Request in Redis.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;

public class RateLimitingMiddleware
{
 private readonly RequestDelegate _next;
 private readonly IDistributedCache _cache;
 private readonly int _maxRequests;
 private readonly TimeSpan _windowSize;

 public RateLimitingMiddleware(RequestDelegate next, IDistributedCache cache)
 {
     _next = next;
     _cache = cache;
     _maxRequests = 10; // Set your max requests
     _windowSize = TimeSpan.FromMinutes(1); // Set your sliding window size
 }

 public async Task InvokeAsync(HttpContext context)
 {
     var key = $"ratelimit:{context.Connection.RemoteIpAddress}";

     var currentRequestCount = await GetRequestCountAsync(key); 
//we will implement this method for Now Assume it gives request count
     if (currentRequestCount &amp;gt;= _maxRequests)
     {
         context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
         await context.Response.WriteAsync("Rate limit exceeded. Try again later.");
         return;
     }
     await IncrementRequestCountAsync(key);
     //we will implement this method for Now Assume it increment request count
     await _next(context);
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Method &lt;code&gt;GetRequestCountAsync&lt;/code&gt; takes string key as parameter. this method then check Redis for Requests for this key. If gets any Request than returns request count else returns 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private async Task&amp;lt;int&amp;gt; GetRequestCountAsync(string key)
 {
     var cacheValue = await _cache.GetStringAsync(key);
     if (cacheValue == null)
     {
         return 0;
     }

     var requestLog = JsonSerializer.Deserialize&amp;lt;List&amp;lt;long&amp;gt;&amp;gt;(cacheValue);
     var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
     requestLog = requestLog.Where(timestamp =&amp;gt; timestamp &amp;gt; currentTime - _windowSize.TotalSeconds).ToList();

     await _cache.SetStringAsync(key, JsonSerializer.Serialize(requestLog), new DistributedCacheEntryOptions
     {
         SlidingExpiration = _windowSize
     });

     return requestLog.Count;
 }

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

&lt;/div&gt;



&lt;p&gt;Method &lt;code&gt;IncrementRequestCountAsync&lt;/code&gt; takes string key as parameter.&lt;/p&gt;

&lt;p&gt;this method calls &lt;code&gt;GetRequestCountAsync&lt;/code&gt; method and checks if there is Requests then add new request in it. else create new Request list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private async Task IncrementRequestCountAsync(string key)
 {
     var cacheValue = await _cache.GetStringAsync(key);
     var requestLog = cacheValue == null ? new List&amp;lt;long&amp;gt;() : JsonSerializer.Deserialize&amp;lt;List&amp;lt;long&amp;gt;&amp;gt;(cacheValue);

     requestLog.Add(DateTimeOffset.UtcNow.ToUnixTimeSeconds());

     await _cache.SetStringAsync(key, JsonSerializer.Serialize(requestLog), new DistributedCacheEntryOptions
     {
         SlidingExpiration = _windowSize
     });
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our RateLimitingMiddleware  with all functions implemented looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;

public class RateLimitingMiddleware
{
 private readonly RequestDelegate _next;
 private readonly IDistributedCache _cache;
 private readonly int _maxRequests;
 private readonly TimeSpan _windowSize;

 public RateLimitingMiddleware(RequestDelegate next, IDistributedCache cache)
 {
     _next = next;
     _cache = cache;
     _maxRequests = 10; // Set your max requests
     _windowSize = TimeSpan.FromMinutes(1); // Set your sliding window size
 }

 public async Task InvokeAsync(HttpContext context)
 {
     var key = $"ratelimit:{context.Connection.RemoteIpAddress}";

     var currentRequestCount = await GetRequestCountAsync(key);

     if (currentRequestCount &amp;gt;= _maxRequests)
     {
         context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
         await context.Response.WriteAsync("Rate limit exceeded. Try again later.");
         return;
     }

     await IncrementRequestCountAsync(key);
     await _next(context);
 }

 private async Task&amp;lt;int&amp;gt; GetRequestCountAsync(string key)
 {
     var cacheValue = await _cache.GetStringAsync(key);
     if (cacheValue == null)
     {
         return 0;
     }

     var requestLog = JsonSerializer.Deserialize&amp;lt;List&amp;lt;long&amp;gt;&amp;gt;(cacheValue);
     var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
     requestLog = requestLog.Where(timestamp =&amp;gt; timestamp &amp;gt; currentTime - _windowSize.TotalSeconds).ToList();

     await _cache.SetStringAsync(key, JsonSerializer.Serialize(requestLog), new DistributedCacheEntryOptions
     {
         SlidingExpiration = _windowSize
     });

     return requestLog.Count;
 }

 private async Task IncrementRequestCountAsync(string key)
 {
     var cacheValue = await _cache.GetStringAsync(key);
     var requestLog = cacheValue == null ? new List&amp;lt;long&amp;gt;() : JsonSerializer.Deserialize&amp;lt;List&amp;lt;long&amp;gt;&amp;gt;(cacheValue);

     requestLog.Add(DateTimeOffset.UtcNow.ToUnixTimeSeconds());

     await _cache.SetStringAsync(key, JsonSerializer.Serialize(requestLog), new DistributedCacheEntryOptions
     {
         SlidingExpiration = _windowSize
     });
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Register middleware
&lt;/h2&gt;

&lt;p&gt;Now ,It is time to add this Register in &lt;code&gt;Program.cs&lt;/code&gt;.&lt;br&gt;
Add app. UseMiddleware(); in  &lt;code&gt;program.cs&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

app.UseMiddleware&amp;lt;RateLimitingMiddleware&amp;gt;();

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run the Application and Check
&lt;/h2&gt;

&lt;p&gt;Set _maxRequests to lower values like 3 or 5 for checking in middleware.&lt;/p&gt;

&lt;p&gt;Now, Run the Application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use tools like Postman or cURL to send multiple requests and verify that after the limit is reached, the server responds with a &lt;code&gt;429 status&lt;/code&gt; code.&lt;/p&gt;

&lt;p&gt;This setup ensures that each IP address is limited to a certain number of requests within a specified sliding window timeframe using Redis for distributed caching. The middleware tracks request timestamps and enforces the rate limit by checking and updating these timestamps in Redis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, rate limitation is essential for controlling API traffic, assuring equitable use, and guarding against overloads and exploitation of the system. It is responsible for preserving the API service's performance and dependability high.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Scaling the Viral App: The Emotional Rollercoaster of Taming Traffic with Consistent Hashing</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Sun, 01 Dec 2024 09:43:10 +0000</pubDate>
      <link>https://dev.to/vizzv/scaling-the-viral-app-the-emotional-rollercoaster-of-taming-traffic-with-consistent-hashing-4em9</link>
      <guid>https://dev.to/vizzv/scaling-the-viral-app-the-emotional-rollercoaster-of-taming-traffic-with-consistent-hashing-4em9</guid>
      <description>&lt;p&gt;In this article, we’ll walk through the technical journey of scaling a viral app, facing the challenges of explosive growth, and a range of approaches to scaling your infrastructure and managing traffic effectively.&lt;/p&gt;

&lt;p&gt;By the end of this article, you’ll understand how to solve the complex problem of data distribution and server scaling when dealing with massive, unpredictable traffic. Let’s dive in!&lt;/p&gt;




&lt;h4&gt;
  
  
  The Calm Before the Chaos
&lt;/h4&gt;

&lt;p&gt;Picture this: after months of relentless effort, your app, a platform for sharing short, funny videos, has finally launched. It’s your dream come true.&lt;/p&gt;

&lt;p&gt;The first six month is steady. A few thousand downloads trickle in, users love the app, and everything runs smoothly. The server hums along like a well-oiled machine. Life is good.&lt;/p&gt;

&lt;p&gt;Then, the unimaginable happens. A very influential and powerful celebrity, Melon Musk, stumbles upon your app, shares a video, and in a matter of hours, your app becomes the hottest thing on the internet.&lt;/p&gt;

&lt;p&gt;Downloads skyrocket. Millions of users sign up overnight, uploading videos, liking, and commenting at a pace you never anticipated. You are on cloud nine. Your servers, though, are not celebrating—they're struggling, then failing. Boom. The app is down.&lt;/p&gt;

&lt;p&gt;You’re no longer living the dream. You’re in a nightmare.&lt;/p&gt;

&lt;h4&gt;
  
  
  The First Fix: Peace Before the Storm
&lt;/h4&gt;

&lt;p&gt;Desperate to bring your app back online, you gather your team. After some time, the issue is spotted. The issue is clear: your database server simply cannot handle the flood of requests.&lt;/p&gt;

&lt;p&gt;What is the &lt;strong&gt;first and fastest solution&lt;/strong&gt;? Make the server bigger. You decide to scale your server vertically. &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%2Fkegut3xofrtocvah7aao.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%2Fkegut3xofrtocvah7aao.png" alt="Verticle Scaling" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You upgrade everything: CPU, memory, storage. Now, the server is more powerful and fast. After a night of frantic work, the app is back. The users are happy. Problem solved. Life is at peace? Not quite.&lt;/p&gt;

&lt;p&gt;Two days later, traffic doubles again. The server, despite its upgrades, crashes under the relentless load. You realize you’ve hit the limits of vertical scaling.&lt;/p&gt;

&lt;p&gt;Why Vertical Scaling Fails&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hardware Limits: No matter how powerful, a single server has a ceiling.&lt;/li&gt;
&lt;li&gt;Cost: Upgrading to high-end hardware is prohibitively expensive.&lt;/li&gt;
&lt;li&gt;Single Point of Failure: One server means one failure point. If it goes down, your entire app goes offline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You need a more robust solution.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Bold Step Forward: Dividing the Load
&lt;/h4&gt;

&lt;p&gt;It’s time to think differently. Your team suggests horizontal scaling: instead of relying on a single powerful server, distribute the load across multiple smaller servers.&lt;/p&gt;

&lt;p&gt;Each server will handle a portion of the data, reducing the burden on any one 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%2Fsol2c7m9dovngi1z0bxn.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%2Fsol2c7m9dovngi1z0bxn.png" alt="Horizontal Scaling" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You think about implement this, and for a while, it seems like a breakthrough.&lt;/p&gt;

&lt;h4&gt;
  
  
  New Problems, New Mysteries
&lt;/h4&gt;

&lt;p&gt;Horizontal Scaling is promising solution. But it also introduces new challenges as traffic grows. In which server data is stored? as we have now multiple instances of server. In which cluster a particular user's data is stored?&lt;/p&gt;

&lt;p&gt;Imagine a user uploads a video. Which server should store it? Later, when someone wants to watch it, how will your system know where to look?&lt;/p&gt;

&lt;p&gt;Your team tries a &lt;strong&gt;Simple and easy&lt;/strong&gt; approach.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Brute Force Method
&lt;/h4&gt;

&lt;p&gt;You decided to use a brute force approach and successfully scaled your server vertically. However, within hours, you received complaints that your app was very slow. This time you know the issue as each server is searched until the data is found. While this approach is simple, it doesn't scale. As the number of servers grows, the time required to locate the data becomes unbearably long, leading to user complaints about slow performance.&lt;/p&gt;

&lt;p&gt;Clearly, brute force isn’t the answer. You need a smarter way to decide where data belongs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hashing: A Glimmer of Hope
&lt;/h4&gt;

&lt;p&gt;You need a way to store data distributed across multiple servers and also able to find that without searching every server.&lt;br&gt;
For that you need to know which server to store the data and where to get the server when read operation.&lt;/p&gt;

&lt;p&gt;Your team proposes to use a mathematical function to organize data. It is simple math function that takes data and output the server number where data need to be stored.&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%2Fw9oalrge9g2o6w8z9xf1.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%2Fw9oalrge9g2o6w8z9xf1.png" alt="Mathematical function to map data to server" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You came up with basic math function : Modulus.&lt;/p&gt;

&lt;p&gt;How It works:&lt;br&gt;
Suppose you have three servers and this modulus function transforms a key (like a userId or VideoId) into number. That number is used to decide which server stores the data.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;You have three servers: Server0, Server1, and Server2.&lt;br&gt;
A video ID is mapped to a value, e.g., hash(5) = Server2.To decide the server, use 5 % 3 = 2. The data is stored on Server Server0.&lt;/p&gt;

&lt;p&gt;Below table depicts which data is mapped to which table.&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%2Fhhu408l4zi31z7bgy3mz.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%2Fhhu408l4zi31z7bgy3mz.png" alt="Modulus function with data" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you need the data, get the server by using the key and modulus function again and go directly to the correct server. No more searching through every server!&lt;/p&gt;

&lt;p&gt;Now this seems propitious, and you proceed to launch this on live. But, after this many emotional roller-coaster you are ready for something bad. However, this time everything is perfect, not any issue.&lt;/p&gt;

&lt;p&gt;A month passed and fortunately, everything is going smoothly. Your app continues to grow steadily, with new users joining at a consistent rate. It’s also gaining more popularity, and the average time users spend on the app is steadily increasing. Things are looking promising, and the future holds even more potential.&lt;/p&gt;

&lt;p&gt;is this &lt;strong&gt;calm before storm&lt;/strong&gt;?&lt;/p&gt;

&lt;h4&gt;
  
  
  The Growth Dilemma: More Servers, More Problems
&lt;/h4&gt;

&lt;p&gt;As your app continues to grow, you realize you need to add another server. But this brings an unexpected problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Happens When You Add a Server?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hash function is based on the number of servers. Adding a new server changes the total, which means every hash value changes. Data previously stored on Server2 might now belong on Server0.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;When you previously have three servers: Server0, Server1, and Server2.&lt;br&gt;
A video ID is hashed to produce a value, e.g., hash(5) = Server2.&lt;br&gt;
To decide the server, use 5 % 3 = 2. The data is stored on Server Server0.&lt;/p&gt;

&lt;p&gt;Now you have four servers: Server0, Server1, Server2, Server3.&lt;br&gt;
A video with Id 5 is previously mapped to 5%3 = 2.&lt;br&gt;
But, Now , that same video with Id 5 is mapped to 5%4 = 1.&lt;/p&gt;

&lt;p&gt;That means data with video Id 5 need to move to Server1.&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%2Fcagmv3x51ssj9y2x27s0.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%2Fcagmv3x51ssj9y2x27s0.png" alt="Modulus function with after adding new instance" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding server leads to inconsistent data across servers. For our case more than 80% of data is in wrong server. So, we have to move data to its relevant server. This process is chaotic, slow, and prone to errors.&lt;/p&gt;

&lt;p&gt;By every time new server is added or removed, we have to move our data to its relevant server and this process is time consuming and can risk of data loss.&lt;/p&gt;

&lt;p&gt;So, we need some better approach that way our functions output keeps consistent irrespective of number of servers. We need to change modulus function to some other consistent function and also need to consider that moving of data should be minimal.&lt;/p&gt;

&lt;h4&gt;
  
  
  Consistent Hashing: The Turning Point
&lt;/h4&gt;

&lt;p&gt;Now, you need a function that maps an input to an output and consistently produces the same output for the same input. Does that sound familiar? Yes, you’re right—we need a hash function, such as MD5 or SHA.&lt;/p&gt;

&lt;p&gt;So, the problem of changing outputs with changes in the number of servers is solved. But now, a new question arises: how do we manage the addition or removal of nodes while ensuring minimal data movement?&lt;/p&gt;

&lt;p&gt;You team came up with an idea- Consistent hashing.&lt;/p&gt;

&lt;p&gt;Consider a system where the hash ring ranges from 0 to 1023, and four servers—server0, server1, server2, and server3—are already present. Their positions on the hash ring might look like this after applying the hash function:&lt;/p&gt;

&lt;p&gt;server0 → Position 100&lt;br&gt;
server1 → Position 300&lt;br&gt;
server2 → Position 600&lt;br&gt;
server3 → Position 900&lt;/p&gt;

&lt;p&gt;Data is also hashed and placed on the ring. For example:&lt;br&gt;
dataA → Position 150 → Stored on server1 (next clockwise server)&lt;br&gt;
dataB → Position 700 → Stored on server3&lt;br&gt;
dataC → Position 50 → Stored on server0.&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%2F0tttev72vngc9dp04hno.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%2F0tttev72vngc9dp04hno.png" alt="Consistent Hashing" width="800" height="1029"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can represent that as array.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;server0 &lt;/th&gt;
    &lt;th&gt;server1 &lt;/th&gt;
    &lt;th&gt;server2 &lt;/th&gt;
    &lt;th&gt;server3 &lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;100&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;600&lt;/td&gt;
    &lt;td&gt;900&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  How to add a new server
&lt;/h4&gt;

&lt;p&gt;If you need a new server, we need Its position in ring and data that needs to be moved in new server. No need to move almost all the data.&lt;/p&gt;

&lt;p&gt;Suppose new server Server4 is added then.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hash new server Server4
For example, Hash(Server4) = 200.&lt;/li&gt;
&lt;li&gt;Moves corresponding data to new server.&lt;/li&gt;
&lt;/ol&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%2Fjbivc2pouyanf0olugro.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%2Fjbivc2pouyanf0olugro.png" alt="Adding Server in Consistent Hashing" width="800" height="1037"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;server0 &lt;/th&gt;
    &lt;th&gt;server4 &lt;/th&gt;
    &lt;th&gt;server1 &lt;/th&gt;
    &lt;th&gt;server2 &lt;/th&gt;
    &lt;th&gt;server3 &lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;100&lt;/td&gt;
    &lt;td&gt;200&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;600&lt;/td&gt;
    &lt;td&gt;900&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Can you see a problem in it?
&lt;/h4&gt;

&lt;p&gt;At first glance, it seems like all things are perfect and there is not any problem with consistent hashing. But there is one. We give our main control to hashing function which basically is pseudo-random function. So, we do not have any control over it, and it can generate new server's position such that it is not impacting any performance improvement.&lt;/p&gt;

&lt;p&gt;Suppose server3 is overloaded and nearing a red zone where it risks going down, you try to add a new server, but hash function places it at 1000.It is impact less. It should be added between 600 and 900.So we can balance load.&lt;/p&gt;

&lt;h4&gt;
  
  
  If there is a problem, then there is a solution also.
&lt;/h4&gt;

&lt;p&gt;The problem with hash function is its randomness, it is needed for data but for server we cannot rely on it as it can be insignificant as we see in above example.&lt;/p&gt;

&lt;p&gt;Our server location is already stored in array. Can't you modify it and add or remove server as we need. Yes, you can. Now, control is again on your hand.&lt;/p&gt;

&lt;p&gt;We can add or remove server exactly where it needed.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;server0 &lt;/th&gt;
    &lt;th&gt;server4 &lt;/th&gt;
    &lt;th&gt;server1 &lt;/th&gt;
    &lt;th&gt;server2 &lt;/th&gt;
    &lt;th&gt;server5 &lt;/th&gt;
    &lt;th&gt;server3 &lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;100&lt;/td&gt;
    &lt;td&gt;200&lt;/td&gt;
    &lt;td&gt;300&lt;/td&gt;
    &lt;td&gt;600&lt;/td&gt;
    &lt;td&gt;700&lt;/td&gt;
    &lt;td&gt;900&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Scaling Without Tears
&lt;/h4&gt;

&lt;p&gt;Now whole scaling problem narrow downs to simple hashing and array problem.&lt;/p&gt;

&lt;p&gt;Adding or removing servers becomes seamless with consistent hashing.&lt;/p&gt;

&lt;p&gt;When a server is added, only data in its immediate range is moved.&lt;br&gt;
When a server is removed, its data is distributed among its neighbors.&lt;br&gt;
This makes scaling fast, efficient, and error-free.&lt;/p&gt;

&lt;h4&gt;
  
  
  What’s Next? Comments, Feedback, and Reviews
&lt;/h4&gt;

&lt;p&gt;I love to hear your thoughts on this topic. Have you faced similar scaling challenges in your apps? How did you overcome them, and how do you see consistent hashing fitting into your solutions? Feel free to share your experiences in the comments below or leave a review. Your feedback helps me keep improving the content and ensure that I am providing value to the community.&lt;/p&gt;

&lt;h4&gt;
  
  
  Conclusion: A Scalable Future
&lt;/h4&gt;

&lt;p&gt;Consistent hashing isn’t just an optimization; it’s a mindset. It’s about building systems that adapt gracefully to growth and change.&lt;/p&gt;

&lt;p&gt;Your viral app, once brought to its knees by traffic, is now ready for anything the internet throws at it. With consistent hashing, you’ve turned chaos into order and laid the foundation for a truly scalable platform.&lt;/p&gt;

&lt;p&gt;And who knows? With these tools, your next big idea might just be the next viral sensation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep learning, keep growing.
&lt;/h3&gt;

</description>
      <category>systemdesign</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>software</category>
    </item>
    <item>
      <title>Why Every Local Business Needs a Professional Website</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Wed, 13 Nov 2024 17:40:24 +0000</pubDate>
      <link>https://dev.to/vizzv/why-every-local-business-needs-a-professional-1go0</link>
      <guid>https://dev.to/vizzv/why-every-local-business-needs-a-professional-1go0</guid>
      <description>&lt;p&gt;In today’s fast-paced, digital-first world, having a strong online presence is no longer a luxury for local businesses — it's a necessity. A professional website serves as the cornerstone of your online identity, acting as your digital storefront that never closes. Whether you're a small boutique, a local restaurant, or an independent service provider, a website offers countless benefits that can help you attract new customers, retain existing ones, and grow your business. In this blog post, we will delve into why every local business needs a professional website, focusing on the importance of an online presence and how a website can help you stay competitive in today’s market.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Builds Credibility and Trust
&lt;/h2&gt;

&lt;p&gt;The first impression matters — and when it comes to your local business, your website is often the first thing potential customers will see. A well-designed and professional website instantly builds credibility. It tells your customers that you are serious about your business and that they can trust you.&lt;/p&gt;

&lt;p&gt;Without a website, your business may appear outdated or unreliable, especially in the eyes of younger, tech-savvy customers who expect to find businesses online. A professional website shows that you're modern, accessible, and ready to serve. Additionally, when customers can easily find essential information like your address, contact details, and hours of operation, they’re more likely to trust you and choose your business over a competitor.&lt;/p&gt;

&lt;p&gt;Make sure your website is search engine optimized (SEO-friendly). Optimizing your website content, including keywords like "local business in [your city]" or "[your product or service] near me", can help your site rank higher in search engine results, making it easier for potential customers to find you. If you have Ice-cream shop then you should be targeting keywords like "Ice-cream shop near me", "best ice cream in Sydney". These type of keywords helps you to get good rank in search engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Improves Local Search Visibility
&lt;/h2&gt;

&lt;p&gt;When people look for services or products online, they often type in specific keywords followed by their location. For example, “best pizza in [city]” or “plumber near me.” Having a professional website helps you take advantage of local SEO. This is a strategy that optimizes your website to rank higher in search results, especially for location-based searches.&lt;/p&gt;

&lt;p&gt;By implementing local SEO techniques such as listing your business on Google My Business, using location-specific keywords, and ensuring your business information is consistent across the web, your website can appear in local searches and on Google Maps. This makes it easier for customers to find your business when they search for services in your area.&lt;/p&gt;

&lt;p&gt;Be sure to claim and optimize your Google My Business profile. Include your business name, address, phone number, and website URL. This will improve your local search rankings and increase the chances of being found by potential customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Attracts New Customers
&lt;/h2&gt;

&lt;p&gt;A website acts as a 24/7 marketing tool for your business. It not only helps you establish an online presence but also works as a powerful lead-generation machine. Through content like blogs, case studies, testimonials, and product pages, a website helps introduce your business to new customers.&lt;/p&gt;

&lt;p&gt;Whether through organic search, social media, or paid advertising, your website serves as the primary destination for anyone looking to learn more about your business. A modern website with clear, easy-to-navigate pages and compelling calls-to-action (CTAs) can convert these visitors into paying customers.&lt;/p&gt;

&lt;p&gt;Additionally, integrating features like an online store or appointment booking system allows potential customers to interact with your business directly from your website, making it easy for them to engage and convert.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Enhances Customer Engagement and Retention
&lt;/h2&gt;

&lt;p&gt;A professional website allows you to engage with customers in ways that go beyond traditional marketing methods. From offering special discounts or promotions to sharing news and updates, your website can be an ongoing source of value for customers.&lt;/p&gt;

&lt;p&gt;Regularly updating your website with blog posts, newsletters, or helpful resources can keep your customers engaged and coming back. Furthermore, having a blog or news section gives you the opportunity to share your expertise, answer common customer questions, and highlight your business’s unique offerings.&lt;/p&gt;

&lt;p&gt;Customer retention can also be increased through loyalty programs, exclusive offers, and a personalized user experience, which can be integrated into your website. Whether it’s creating an account to track their purchases or sending them personalized email offers, a well-designed website allows for a more connected and personalized relationship with your customers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Interested in engaging your customers online? I can help you design a website with loyalty programs, special offers, and personalized experiences. &lt;a href="//mailto:vishw.m.patel@gmail.com"&gt;Reach out&lt;/a&gt; to discuss your options.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Boosts Competitive Advantage
&lt;/h2&gt;

&lt;p&gt;In today’s competitive market, businesses that fail to have a website are at a significant disadvantage. Without an online presence, customers may not even know your business exists, or worse, they might think your business is outdated or not professional.&lt;/p&gt;

&lt;p&gt;A website allows you to share detailed information about your products or services, display customer reviews, and showcase your unique selling proposition (USP). This way, customers can easily understand why your business is the best choice.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stand out from your competitors with a website that highlights your unique selling points. &lt;a href="//mailto:vishw.m.patel@gmail.com"&gt;Let’s talk&lt;/a&gt; about how to make your business shine online.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  6. Increases Sales and Revenue
&lt;/h2&gt;

&lt;p&gt;A website has the potential to directly increase your sales and revenue. If you’re running a retail business, an e-commerce platform can open up a new revenue stream by allowing customers to purchase products directly from your website.&lt;/p&gt;

&lt;p&gt;With e-commerce integrations, such as secure payment gateways, you can offer customers a seamless and secure shopping experience. This is particularly important for building trust with online customers who are unfamiliar with your business.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Looking to boost sales? I specialize in creating e-commerce platforms and booking systems to help you increase your revenue. &lt;a href="//mailto:vishw.m.patel@gmail.com"&gt;Contact me&lt;/a&gt; to start building an online sales channel for your business.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  where to build Seo friendly website
&lt;/h2&gt;

&lt;p&gt;For personalized help in building an SEO-optimized website, feel free to reach out. I specialize in web development, SEO strategy, and content optimization to help businesses maximize their online presence.&lt;/p&gt;

&lt;p&gt;📧 Email: &lt;a href="mailto:vishw.m.patel@gmail.com"&gt;vishw.m.patel@gmail.com&lt;/a&gt;&lt;br&gt;
Skills: SEO, Web Design, Web Development, Content Strategy, and Digital Marketing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In today’s digital landscape, every local business should have a professional website. Not only does it help establish credibility and trust, but it also provides a competitive advantage, enhances customer engagement, and boosts sales. A website acts as a 24/7 marketing tool, helping you connect with customers, increase visibility, and stay ahead of the competition. By implementing SEO strategies and regularly updating your website, you can ensure that your business is well-positioned to attract and retain local customers. If you haven’t already, it’s time to invest in a professional website for your business — it’s the key to unlocking long-term success in the modern marketplace.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ready to take your business online? If you’re looking to create or improve your website with e-commerce integrations, scheduling, or service management, &lt;a href="//mailto:vishw.m.patel@gmail.com"&gt;get in touch today&lt;/a&gt;. I’ll help you build the digital tools needed to stay competitive and drive growth.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>website</category>
      <category>startup</category>
      <category>webdev</category>
      <category>online</category>
    </item>
    <item>
      <title>Building a Real-Time Chat Application with .NET Core 7 and SignalR</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Sun, 10 Nov 2024 05:39:55 +0000</pubDate>
      <link>https://dev.to/vizzv/building-a-real-time-chat-application-with-net-core-7-and-signalr-2853</link>
      <guid>https://dev.to/vizzv/building-a-real-time-chat-application-with-net-core-7-and-signalr-2853</guid>
      <description>&lt;p&gt;&lt;strong&gt;SignalR&lt;/strong&gt; is a library for ASP.NET that enables real-time web functionality, allowing servers to push updates to clients instantly, enhancing efficiency and responsiveness in applications. It's useful for instant updates in chat apps, live dashboards, and collaborative tools by simplifying communication and supporting various transport protocols. Real-time communication boosts user engagement, reduces resource-intensive polling, and is essential for interactive applications like online gaming and financial trading platforms, providing seamless and dynamic user experiences.&lt;/p&gt;

&lt;p&gt;This article will show you how to build a real-time chat application with &lt;strong&gt;.Net Core 7&lt;/strong&gt; and &lt;strong&gt;SignalR&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SignalR?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SignalR&lt;/strong&gt; is a library for ASP.NET that enables real-time web functionality. SignalR uses WebSockets to establish persistent connections between the server and the client, if available. If WebSockets are not available, SignalR relies  on other suitable transport protocols such as Server-Sent Events or Long Polling to ensure broad compatibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The foundation of SignalR's functionality is based on "Hubs", which are high-level pipeline APIs that enable the server to call methods on connected clients and vice versa. Developers create Hub classes, which contain methods that may be invoked by clients. The client then calls these methods with JavaScript, and SignalR handles the communication details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SignalR supports grouping connections, which allows messages to be sent to a specific subset of connected clients. This is useful for scenarios like chat rooms, where only certain users should receive specific messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SignalR controls connection lifecycles and automatically handles reconnections when a connection is lost. This ensures that the server and clients communicate reliably without forcing the developer to do anything extra.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server can automatically push updates to clients using the technique provided by SignalR. Because of this, clients may communicate in real-time more effectively and the server burden is decreased without having to query the server for updates.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to create a Real-Time Chat Application with .NET Core 7 and SignalR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Setting up the project&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Let's start by making a new ASP.NET Core 7 project. In Visual Studio, choose "Create a new project" after opening. Give the project a name and select "ASP.NET Core Web Application" as the project type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, choose the project template "Web Application" and ensure that "Enable Docker Support" is not checked. To begin creating the project, click "Create".&lt;/p&gt;&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%2Fcz24hpenzc3frq7xuj0t.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%2Fcz24hpenzc3frq7xuj0t.png" alt="Dotnet project setup" width="612" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the "Program.cs" file after the project has been created, then add the following code to add SignalR:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
builder.Services.AddSignalR();
builder.Services.AddControllersWithViews();

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Now Add the SignalR client library to our Project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Solution Explorer, right-click the project, and select Add &amp;gt; Client-Side Library.&lt;/p&gt;&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%2F0gc4qwz9qdiuwndri74m.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%2F0gc4qwz9qdiuwndri74m.png" alt="Add Client-side library" width="765" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Add Client-Side Library dialog:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt; Select unpkg for Provider.&lt;/li&gt;
&lt;li&gt; Enter @microsoft/signalr@latest for Library.&lt;/li&gt;
&lt;li&gt; Select Choose specific files, expand the dist/browser folder, and select signalr.js and signalr.min.js.&lt;/li&gt;
&lt;li&gt; Set Target Location to wwwroot/js/signalr/.&lt;/li&gt;
&lt;li&gt; Select Install.&lt;/li&gt;
&lt;/ol&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%2F51qlwd2ace1au3cfdj0o.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%2F51qlwd2ace1au3cfdj0o.png" alt="Clientside library" width="544" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Creating the Hub&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder named Hubs.&lt;/li&gt;
&lt;li&gt;To create a new folder right click on solution,then click on Add and now click on Add Folder.(Add&amp;gt;Add Folder).&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%2Fehbmikkf9w3mdkzntavl.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%2Fehbmikkf9w3mdkzntavl.png" alt="Hub" width="788" height="732"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rename this newly created to Hubs.&lt;/li&gt;
&lt;li&gt;Every real-time communication between the client and the server will be managed through the Hub. In our project's "Hubs" folder, let's build a new class named "ChatHub".&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%2F6ayfi8ffk58lu9xjlnfc.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%2F6ayfi8ffk58lu9xjlnfc.png" alt="Add Hub" width="687" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;flood class with below code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;

namespace YourProjectName.Hubs
{
    public class ChatHub : Hub
    {
        public async Task Message(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
            //this will be listen by client using javascript.
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This will create a new Hub class inherited from SignalR Hub .We define method named Message,that takes two string parameters user and message , and SendAsync method send messages to all the connected clients.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However ,Before using ChatHub ,we have to Configure It in Program.cs&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//...
app.MapHub&amp;lt;ChatHub&amp;gt;("chatHub");
//...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This line configures the SignalR middleware to use the Chat Hub by mapping the "/chatHub" URL to the ChatHub class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Creating UI&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After implementing the Chat Hub, we still need to design the user interface (UI) for our chat program. For real-time communication in this tutorial, a basic HTML page with some JavaScript code will be used.&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%2Fj7u9fbs9nsftli7px2cf.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%2Fj7u9fbs9nsftli7px2cf.png" alt="Main Ui Page" width="353" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the following code to your project's "index.cshtml" file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@{
Layout = null;
}
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset="utf-8" /&amp;gt;
    &amp;lt;title&amp;gt;
        SignalR Chat
    &amp;lt;/title&amp;gt;
    &amp;lt;script src=
"https://code.jquery.com/jquery-3.6.0.min.js"&amp;gt;
    &amp;lt;/script&amp;gt;
    &amp;lt;script src=
"https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.13/signalr.min.js"&amp;gt;
    &amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;input id="username" placeholder="username" 
               type="text" /&amp;gt;
        &amp;lt;input id="message" placeholder="message"
               type="text" /&amp;gt;
        &amp;lt;button id="send-btn"&amp;gt;
            Send
        &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div id="chatBox"&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;script&amp;gt;
        let connection = new signalR.HubConnectionBuilder()
                                    .withUrl("/chatHub").build();
        connection.on("ReceiveMessage", function (User, Message) {
            let encodedUser = $("&amp;lt;div /&amp;gt;").text(user).html();
            let encodedMsg = $("&amp;lt;div /&amp;gt;").text(message).html();
            $("#chatBox").append("&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;" + encodedUser + "&amp;lt;/strong&amp;gt;: " + encodedMsg + "&amp;lt;/p&amp;gt;");
        });

        $("#send-btn").click(function () {
            let our_user = $("#username").val();
            let Message = $("#message").val();
            connection.invoke("Message", our_user, Message);
            $("#message").val("").focus();
        });


        connection.start().then(function () {
            console.log("Connected!");
        }).catch(function (err) {
            console.error(err.toString());
        });
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This code generates a simple user interface (UI) containing a "Send" button, an input form for the message, and a field for the user's name. Additionally, a div with the id "chatBox" is created, and this is where the chat messages will be shown.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using the URL "/chatHub" (which we mapped to our ChatHub class in the "Startup.cs" file), we establish a new SignalR connection in the JavaScript code. The "ReceiveMessage" event, which is triggered each time a message is sent from the server to the client, is then handled by a function that we define. The message is appended to the chatBox div using this function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additionally, we construct a click event handler for the "Send" button that sends the user's name and message to the server using the "Message" method. Lastly, we initiate the SignalR connection and, upon connection establishment, log a message to the console.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Running the application&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now is the time to start the application To launch the program in debug mode, press F5. You should be able to view the chat UI with the input fields and the "Send" button as soon as the application launches.&lt;/li&gt;
&lt;li&gt;After putting in your name and a message, click "Send". Your message will  pop up in the chat window. Navigate to the same URL in an other browser window. Send a message and enter a different name. The message appears in both windows.&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%2Foue4r5bjf8bmx4jl1fqp.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%2Foue4r5bjf8bmx4jl1fqp.png" alt="RealTime chat app with dotnet and signalR" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, you've just built a real-time chat application with .NET Core 7 and SignalR!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article demonstrates how to use SignalR and.NET Core 7 to create a real-time chat application. The fundamentals of project setup, Chat Hub creation, and Chat UI creation have all been addressed. We hope that this article has given you a better understanding of SignalR's capabilities and how to use them to create real-time web applications. Have fun with coding!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>api</category>
      <category>dotnetcore</category>
    </item>
  </channel>
</rss>
