<?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: Michael Owolabi</title>
    <description>The latest articles on DEV Community by Michael Owolabi (@imichaelowolabi).</description>
    <link>https://dev.to/imichaelowolabi</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%2F99010%2F1a70f564-31af-4802-adea-470e871b5960.png</url>
      <title>DEV Community: Michael Owolabi</title>
      <link>https://dev.to/imichaelowolabi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imichaelowolabi"/>
    <language>en</language>
    <item>
      <title>Build a Passwordless Authentication in Node.js on Redis</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Fri, 30 Sep 2022 23:00:04 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/passwordless-authentication-in-nodejs-on-redis-12e</link>
      <guid>https://dev.to/imichaelowolabi/passwordless-authentication-in-nodejs-on-redis-12e</guid>
      <description>&lt;p&gt;One of the most important and universal aspects of Software Development is how access to various services in the application is granted, over the years, many authentication models have been developed with various pros and cons. There is really no single perfect auth system without any flaws. It is impossible to have a system that is both “very” secure and convenient to use at the same time. The more we tend towards the side of “security”, the more difficult the user experience for most users, and various models have been developed to find that balance.&lt;br&gt;
What is more practicable is to find what is more important in various use cases and apply it accordingly.&lt;/p&gt;

&lt;p&gt;Like various other security systems have their origin traced back to the Roman empire, so can passwords be traced to the same root according to this &lt;a href="https://en.wikipedia.org/wiki/Password" rel="noopener noreferrer"&gt;Wikipedia page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Password has evolved a lot since its introduction and many encryption models have been developed over the years just to curb various password attacks. Sometimes, it’s not even that the password encryption model isn’t secure enough, in fact, most password breach is caused by human errors ranging from companies storing passwords in plain text, to users using weak passwords or just being careless or too trusting with their passwords.&lt;/p&gt;

&lt;p&gt;Truth is that, as long as password exists, all these will continue to be an issue.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The most secure password is no password at all because, “If it exists, it can be cracked”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What if we can eradicate passwords completely and be done with all the associated issues?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fx2kczjjstznpxxc0d75o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fx2kczjjstznpxxc0d75o.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we are going to develop a password-less authentication system built on Redis where all the problems discussed above can be a thing of the past.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that I’m not saying that this will be the most secure system, but at least we can be sure that our system will still be secured without all the associated problems listed above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why Redis for such an application you asked? For the simple reason that traditional databases are slow and Redis is super fast. We wouldn’t want our users to wait too long before they will be able to access our system now that the password is out of the way, would we? So let’s get to it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;To be able to follow along with this tutorial, you need to have the following installed on your computer:&lt;br&gt;
Node.js&lt;br&gt;
npm&lt;br&gt;
Code Editor (VSCode)&lt;br&gt;
Postman/Web Browser&lt;br&gt;
&lt;a href="https://signup.mailgun.com/new/signup" rel="noopener noreferrer"&gt;Mailgun Account&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RedisInsight - Get one installed on your computer &lt;a href="https://redis.com/redis-enterprise/redis-insight/" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you don’t already have one.&lt;/p&gt;

&lt;p&gt;Finally, you’ll need to have a Redis Enterprise account for your Redis cloud database. If you don’t already have that just head on to their &lt;a href="https://redis.com/try-free/" rel="noopener noreferrer"&gt;website&lt;/a&gt; to create a free account.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;First, we are going to install the dependencies needed for this application so open your terminal and execute the following commands&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd desktop &amp;amp;&amp;amp; mkdir passwordless-authentication &amp;amp;&amp;amp; cd passwordless-authentication


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

&lt;/div&gt;
&lt;p&gt;Initialize the directory to create a package.json file by running&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm init -y


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Install dependencies
&lt;/h3&gt;

&lt;p&gt;Let’s install the various packages that we’ll be using for the development of this application by running the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm i express dotenv redis-om jsonwebtoken nodemailer


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

&lt;/div&gt;
&lt;p&gt;Lastly, let’s install nodemon as a dev dependency to aid our development flow by running the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm i -D nodemon


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

&lt;/div&gt;
&lt;p&gt;Now let’s create a simple Node.js server using express so as to be sure that everything is properly set up. To do this, create a new directory at the root of your project named “src” and inside it create a new file called index.js and paste the code below into the file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the scripts section of your package.json file setup the start scripts for your server by adding the following keys and values&lt;/p&gt;

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

"start": "nodemon index.js"


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

&lt;/div&gt;

&lt;p&gt;Now start the server by running &lt;code&gt;npm start&lt;/code&gt;` in the terminal. You should see something close to the screenshot below logged to your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5q4rj1ansvx1rbvfxxcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5q4rj1ansvx1rbvfxxcm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we are sure that our server is properly set up, the next thing we need to do is set up our Redis database to handle the storage of our events data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redis Enterprise Setup
&lt;/h3&gt;

&lt;p&gt;To setup your Redis database, login to your Redis enterprise account &lt;a href="https://app.redislabs.com/#/login" rel="noopener noreferrer"&gt;here&lt;/a&gt;. If you haven’t created an account yet just head on to the &lt;a href="https://redis.com/try-free/" rel="noopener noreferrer"&gt;Redis website&lt;/a&gt; and create a free account. You should use the free credit coupon on the signup page to explore Redis beyond the free tier offerings.&lt;/p&gt;

&lt;p&gt;On your Redis enterprise dashboard click the &lt;em&gt;“New subscription”&lt;/em&gt; button, select &lt;em&gt;“Fixed plans”&lt;/em&gt; and then choose the 100MB storage space option. You can choose any cloud provider of your choice but for the sake of this tutorial, let’s use the default (AWS) then make sure your settings are a replica of the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F60oyhwh3l4xp5tpg8nsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F60oyhwh3l4xp5tpg8nsy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not worry, you will not get charged for the plan you chose since you applied a &lt;strong&gt;$200 coupon&lt;/strong&gt; so you can safely add your card. We needed this plan to activate data persistence for our Redis DB because it will be odd to have an event management platform where every time you come back to it, it’s always empty 😀.&lt;/p&gt;

&lt;p&gt;But just if you’re still skeptical you can choose the free (30MB) option only that your data will not be persisted but you would still be able to follow along with this tutorial using that option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5cxo643f4bh9qx8p3z87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5cxo643f4bh9qx8p3z87.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now on your subscription dashboard, click on the  “New Database button”. Give your database a name and choose the Redis option under the “Type section” to specifically select the Redis module of choice which in our case is RediSearch and RedisJSON.&lt;/p&gt;

&lt;p&gt;Make sure you also select the data persistence option of choice but in this case, we’ll be using the snapshot option that runs every hour. Click the “Activate database” button when you’re done to provision your database. After that, you should see the database configuration screen similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fiq2v30otaolsr1oir220.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fiq2v30otaolsr1oir220.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualizing your data
&lt;/h3&gt;

&lt;p&gt;Now that we have set up our database properly, we need something to visualize our data stored in the Redis DB and this is where &lt;a href="https://redis.com/redis-enterprise/redis-insight/" rel="noopener noreferrer"&gt;RedisInsight&lt;/a&gt; comes in. Now launch your RedisInsight and click the &lt;strong&gt;“Add Redis Database”&lt;/strong&gt; button then copy and paste in your Redis enterprise DB connection string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fznz5hdoauhsy349kz9n6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fznz5hdoauhsy349kz9n6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is called &lt;strong&gt;&lt;em&gt;“public endpoint”&lt;/em&gt;&lt;/strong&gt; on your Redis enterprise DB configuration page. Then on the same DB configuration page, you would see your default username and password, copy those and paste them into your RedisInsght connection dialog after which you click the “Add Redis Database” button to connect to your Redis enterprise DB. You should see the DB summary on the next page which will be empty since there’s currently no data in your Redis database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fozt31q983qrloa4iuqcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fozt31q983qrloa4iuqcv.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting your Redis DB from the App
&lt;/h3&gt;

&lt;p&gt;The next thing to do is to set up a connection to our Redis database from within the event manager app. To do this, create a new directory inside "src" called db and create a new file named &lt;strong&gt;"index.js"&lt;/strong&gt; in the newly created db directory. Copy and paste the following code into the file.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/ab7e7144aa3ea5e6033e7cdd22a2ee70" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/ab7e7144aa3ea5e6033e7cdd22a2ee70&lt;/a&gt; %}&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Passwordless Authentication
&lt;/h3&gt;

&lt;p&gt;Now that all the building blocks have been set, let’s dive into building our authentication system without passwords.&lt;/p&gt;

&lt;p&gt;The first thing we are going to do is to model our entity for authentication purpose. We will allow users to be able to log in with either their email or username so to do this, let’s create a directory in the src directory and name it repository. Inside the newly created repository, create a file called &lt;strong&gt;user.js&lt;/strong&gt; and paste into it the code below.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/c7dbc25e6706236e00c958edf0699068" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/c7dbc25e6706236e00c958edf0699068&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;Here, we have modeled our authentication data and assigned the individual fields with the proper data type which is mostly string. You will notice that in the date fields, we have a new attribute “sortable”, this is something similar to “ORDER BY” in SQL which allows us to order the result of our query. In this case, we could fetch all users and order them from the most recently created to the least recent users.&lt;/p&gt;

&lt;p&gt;We create an index on our user model by calling the &lt;code&gt;"createIndex()"&lt;/code&gt; method on the repository from our schema. This secondary index is where the power of RediSearch shines the most. The performance of our search is directly proportional to how good our index is.&lt;/p&gt;

&lt;p&gt;We’ll create a new directory in the src folder and name it routes. Inside the routes directory let’s create a new file called &lt;strong&gt;"authRouter.js"&lt;/strong&gt; and paste in the following code:&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/0494dfab097b457855915367595b54d0" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/0494dfab097b457855915367595b54d0&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;This router file is where all our endpoints for the app is defined and it’s responsible for routing requests to the right controller function for execution.&lt;/p&gt;

&lt;p&gt;You’ll notice that we imported some controller functions and a middleware into the authRouter file, so let’s go ahead and build them out. These auth methods here aren’t anything new that we haven’t seen before, the only difference is that instead of interfacing with traditional relational or Doc DB that directly write and read from the disk, we are using the super fast Redis as our DB which in turn makes our user authentication process fast.&lt;/p&gt;

&lt;p&gt;So, create a new folder named controllers inside the src directory. In the newly created directory, create a new file named &lt;strong&gt;"authController.js"&lt;/strong&gt; and paste the following code into it.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/06cd1053d7e653ba920f0da725ac6e07" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/06cd1053d7e653ba920f0da725ac6e07&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;In the code above, you could see some SQL-like query structure which makes the entire thing very friendly, this is made possible by &lt;a href="https://github.com/redis/redis-om-node" rel="noopener noreferrer"&gt;Redis-om&lt;/a&gt; which is a new Redis client from &lt;a href="https://redis.com/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s sort out the dependent modules that we used in the auth controller file.&lt;/p&gt;

&lt;p&gt;Even though our aim is to eliminate password from our authentication process in this app, we still need to make it secure else, we run the risk of allowing the entire Internet access to resource that shouldn’t be in the public view. So let’s create a new directory called utils straight inside the src directory. In the utils folder, create two new files namely, &lt;strong&gt;"jwtHelper.js"&lt;/strong&gt; and &lt;strong&gt;"emailTransporter.js"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the jwtHelper file copy and paste the following piece of code into it.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/94d5a7282fe813b5bcffe970a35b93bc" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/94d5a7282fe813b5bcffe970a35b93bc&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;Our approach to authenticate user simply involves sending the login credentials to the user’s email which serves as a means verification that even though the user isn’t using password to access their protected contents, we can still be sure they’re the ones requesting access that way which makes the system secure still.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up email service
&lt;/h3&gt;

&lt;p&gt;To send email, we need to user an email service provider and for the sake of this article, we are going to use Mailgun. To be able to send free emails, we need to add verified recipient so log in to your Mailgun account and click “sending” from the sidebar, from the list of dropdown options click “Domains”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fithmaw9wcamv856cj213.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fithmaw9wcamv856cj213.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see the default domain provided you by Mailgun. Now click on the domain and you should see where you can add list of emails for verification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2crazf5ucs1rx1qhhvr8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2crazf5ucs1rx1qhhvr8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add the email you will be sending messages to for test purpose and verify the mail by accepting the terms from the email sent to the added email account. Something similar to what we have below.&lt;/p&gt;

&lt;p&gt;Now that we’ve setup our email service, let’s plug it to the app so copy and paste the following code into the "emailTransporter" file.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/4da4997767773f314914dbdefbd5c4db" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/4da4997767773f314914dbdefbd5c4db&lt;/a&gt; %}&lt;/p&gt;

&lt;p&gt;We are getting closer to the end of the application. Let’s protect some of our endpoints from being accessible to unauthorized users. Create a new folder in the src directory named “middleware” then create a new file in the new folder called &lt;strong&gt;"index.js"&lt;/strong&gt; and paste the code below into the file.&lt;/p&gt;

&lt;p&gt;{% embed &lt;a href="https://gist.github.com/iMichaelOwolabi/5aa9ac993e3104aa7673143c135111c0" rel="noopener noreferrer"&gt;https://gist.github.com/iMichaelOwolabi/5aa9ac993e3104aa7673143c135111c0&lt;/a&gt; %}&lt;/p&gt;

&lt;h3&gt;
  
  
  Bringing it altogether
&lt;/h3&gt;

&lt;p&gt;Now that we’re done building the individual parts of the application, we need to find a way to make sure our server is aware of our routes so we are going to plug our auth router to the server by importing it to the index.js file at the root of the project. Just copy the following code and replace the content of the index.js file with it.&lt;/p&gt;

&lt;p&gt;Lastly create a new file at the root of your project named &lt;strong&gt;".env"&lt;/strong&gt;&lt;br&gt;
The env file is what we are going to use to store the secret values used in the app so that they’re not exposed to the public. In the env file, copy and paste the following then populate the values accordingly.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
PORT=&lt;br&gt;
REDIS_DB_URL=&lt;br&gt;
REDIS_DB_USER=&lt;br&gt;
REDIS_DB_PASS=&lt;br&gt;
TOKENEXPIRATIONTIME=&lt;br&gt;
JWTSECRET=&lt;/p&gt;

&lt;p&gt;MAILGUN_SMTP_HOSTNAME=&lt;br&gt;
SMTP_PORT=&lt;br&gt;
MAILGUN_SMTP_USERNAME=&lt;br&gt;
MAILGUN_SMTP_PASSWORD=&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We have successfully built a passwordless authentication system in Node.js powered by Redis.&lt;/p&gt;

&lt;p&gt;Startup your server by running the following command from your terminal right from the project directory&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
npm start&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let’s test our implementations so far. Open Postman and create a user account, login and verify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a user account&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fb21pw4rfzmsb94yef6sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fb21pw4rfzmsb94yef6sb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fh8cvrb954clikwhpwd5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fh8cvrb954clikwhpwd5x.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Login screenshot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fykkd3c3wuzqrsgbd9y4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fykkd3c3wuzqrsgbd9y4v.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fd0tevajdp3kjq8j99hu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fd0tevajdp3kjq8j99hu0.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations on making it this far. Do share your thoughts in the comment section.&lt;/p&gt;

&lt;p&gt;The complete code can be found in this &lt;a href="https://github.com/iMichaelOwolabi/passwordless-authentication" rel="noopener noreferrer"&gt;Github Repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This post is in collaboration with Redis.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you enjoyed working with us like we enjoyed working with you and want to continue writing for us, we’re now accepting applications for more blogs. You can apply &lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSd_yuc3-l6ojw_W4N8H3ueLe1ZBcrAWUawi4CPIlwIpXqF7QA/viewform" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>redis</category>
      <category>node</category>
      <category>auth</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to build an event management application in Node.js + React on Redis</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Wed, 06 Jul 2022 18:12:37 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/how-to-build-an-event-management-application-in-nodejs-react-on-redis-165</link>
      <guid>https://dev.to/imichaelowolabi/how-to-build-an-event-management-application-in-nodejs-react-on-redis-165</guid>
      <description>&lt;p&gt;You’re probably thinking, wait, did I read the title right? Build an event manager in Node.js and backed by Redis as the database? Just follow along and let me take you on a journey that will provide answers to as many questions as are probably going through your head right now.&lt;/p&gt;

&lt;p&gt;In this article, we are going to build a fully functional event management platform on Redis but first, why will anyone want to use Redis as the only database in an application? One obvious reason will be that Redis is super fast, and fast database will have a direct impact on the performance of your application which will in turn impact the experience of the users of your application. So having said that, let’s get to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;To be able to follow along with this tutorial, you need to have the following installed on your computer:&lt;br&gt;
Node.js&lt;br&gt;
npm&lt;br&gt;
Code Editor (VSCode)&lt;br&gt;
Web browser/Postman&lt;br&gt;
RedisInsight - Get one installed on your computer &lt;a href="https://redis.com/redis-enterprise/redis-insight/" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you don’t already have one.&lt;/p&gt;

&lt;p&gt;Finally, you’ll need to have a Redis Enterprise account for your Redis cloud database. If you don’t already have that just head on to their &lt;a href="https://redis.com/try-free/" rel="noopener noreferrer"&gt;website&lt;/a&gt; to create a free account.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;To get started, we are going to install dependencies needed for the application so open up your terminal (Command prompt on Windows) and enter the following command&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd desktop &amp;amp;&amp;amp; mkdir event-manager &amp;amp;&amp;amp; cd event-manager


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

&lt;/div&gt;
&lt;p&gt;Initialize the directory to create a package.json file by running&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm init -y


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Install dependencies
&lt;/h3&gt;

&lt;p&gt;Let’s install the various packages that we’ll be using for the development of this application by running the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install express dotenv redis-om ulid jsonwebtoken bcrypt


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

&lt;/div&gt;
&lt;p&gt;Lastly, let’s install nodemon as a dev dependency to aid our development flow by running the command below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install -D nodemon


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

&lt;/div&gt;
&lt;p&gt;Open the newly created app event-manager directory in your code editor of choice (I will be using VSCode here) and it should be similar to what we have below.&lt;/p&gt;

&lt;p&gt;Open the generated &lt;em&gt;"package.json"&lt;/em&gt; file and enter a key "type" with the value "module" in the top-level object because we will be writing our development code using the es module option.&lt;/p&gt;

&lt;p&gt;Now let’s create a simple express server to be sure that everything is properly set up. To do this, create a new directory at the root of your project named “src” and inside it create a new file called app.js and paste the code below into the file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the scripts section of your package.json file setup the start scripts for your server by adding the following keys and values&lt;/p&gt;

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

“start”: “node src/app.js”,
“dev”: nodemon src/app.js”


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

&lt;/div&gt;
&lt;p&gt;Now start your node.js server by running the following command in the terminal:&lt;br&gt;
npm run dev&lt;br&gt;
You should see the following logged to your terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F7mn7eysfgm7b2d6zu1qt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7mn7eysfgm7b2d6zu1qt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everytime you make changes to your application code, the server should automatically restart to pick the new changes.&lt;/p&gt;

&lt;p&gt;Now that we are sure that our server is properly setup, the next thing we need to do is setup our Redis database to handle the storage of our events data.&lt;/p&gt;
&lt;h3&gt;
  
  
  Redis Enterprise Database Setup
&lt;/h3&gt;

&lt;p&gt;To setup your Redis database, login to your Redis enterprise account &lt;a href="https://app.redislabs.com/#/login" rel="noopener noreferrer"&gt;here&lt;/a&gt;. If you haven’t created an account yet just head on to the &lt;a href="https://redis.com/try-free/" rel="noopener noreferrer"&gt;Redis website&lt;/a&gt; and create a free account. You should use the free credit coupon on the signup page to explore Redis beyond the free tier offerings.&lt;/p&gt;

&lt;p&gt;On your Redis enterprise dashboard click the &lt;em&gt;“New subscription”&lt;/em&gt; button, select &lt;em&gt;“Fixed plans”&lt;/em&gt; and then choose the 100MB storage space option. You can choose any cloud provider of your choice but for the sake of this tutorial, let’s use the default (AWS) then make sure your settings are a replica of the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F60oyhwh3l4xp5tpg8nsy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F60oyhwh3l4xp5tpg8nsy.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not worry, you will not get charged for the plan you chose since you applied a &lt;strong&gt;$200 coupon&lt;/strong&gt; so you can safely add your card. We needed this plan to activate data persistence for our Redis DB because it will be odd to have an event management platform where every time you come back to it, it’s always empty 😀.&lt;/p&gt;

&lt;p&gt;But just if you’re still skeptical you can choose the free (30MB) option only that your data will not be persisted but you would still be able to follow along with this tutorial using that option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5cxo643f4bh9qx8p3z87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5cxo643f4bh9qx8p3z87.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now on your subscription dashboard, click on the  “New Database button”. Give your database a name and choose the Redis option under the “Type section” to specifically select the Redis module of choice which in our case is RediSearch. Make sure you also select the data persistence option of choice but in this case, we’ll be using the snapshot option that runs every hour. Click the “Activate database” button when you’re done to provision your database. After that, you should see the database configuration screen similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ft1ftin94fxihfuccfzfn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ft1ftin94fxihfuccfzfn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Visualizing your data
&lt;/h3&gt;

&lt;p&gt;Now that we have set up our database properly, we need something to visualize our data stored in the Redis DB and this is where &lt;a href="https://redis.com/redis-enterprise/redis-insight/" rel="noopener noreferrer"&gt;RedisInsight&lt;/a&gt; comes in. Now launch your RedisInsight and click the &lt;strong&gt;“Add Redis Database”&lt;/strong&gt; button then copy and paste in your Redis enterprise DB connection string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fznz5hdoauhsy349kz9n6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fznz5hdoauhsy349kz9n6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is called &lt;strong&gt;&lt;em&gt;“public endpoint”&lt;/em&gt;&lt;/strong&gt; on your Redis enterprise DB configuration page. Then on the same DB configuration page, you would see your default username and password, copy those and paste them into your RedisInsght connection dialog after which you click the “Add Redis Database” button to connect to your Redis enterprise DB. You should see the DB summary on the next page which will be empty since there’s currently no data in your Redis database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fozt31q983qrloa4iuqcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fozt31q983qrloa4iuqcv.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Connecting your Redis DB from the App
&lt;/h3&gt;

&lt;p&gt;The next thing to do is to set up a connection to our Redis database from within the event manager app. To do this, create a new directory inside “src” called db and create a new file named index.js in the newly created db directory. Copy and paste the following code into the file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Building user authentication into our event manager app
&lt;/h3&gt;

&lt;p&gt;Even though we want the general public to be able to view events on our platform, we only want registered users to be able to create events. So let’s build some authentication into the system. In the &lt;em&gt;src&lt;/em&gt; directory create four folders namely &lt;em&gt;routes, controller, utils,&lt;/em&gt; and lastly &lt;em&gt;middleware&lt;/em&gt;. We are doing this to keep things simple and clean to some extent.&lt;/p&gt;

&lt;p&gt;Now, in the controller directory, create a new file called “auth.js” and paste the following code into it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the &lt;strong&gt;&lt;em&gt;createAccount()&lt;/em&gt;&lt;/strong&gt; function part of the codebase, we are saving the user account information in a Redis hash data structure and using the user’s email as the key since it will be unique across the entire database. We are generating a user ID for the user with the help of the ulid package which is a great alternative to uuid. We are interfacing with our Redis enterprise DB with the help of the "redis-om" client via the DB connection that we setup earlier.&lt;/p&gt;

&lt;p&gt;The last thing that we need to do is create the jwt helper file that was imported here so create a new file under the utils directory called &lt;em&gt;"jwtHelper.js"&lt;/em&gt; and then copy and paste the following code into the file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The next thing to do is to connect our controller to a route. In the routes directory, create a file named “authRouter.js” then copy and paste the following code into it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now let’s ultimately connect our router to our express server. In the app.js file import the “authRouter” module and adding it to the server middleware stack by passing it to the use() function as below.&lt;/p&gt;

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

app.use('/api/v1/auth', authRouter);


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

&lt;/div&gt;
&lt;p&gt;Lastly, let’s create a new file at the root of the project directory called .env so that we can add all our secrets to it. Remember we’ve been using them across the project so copy and paste the following environment variables to your .env file and fill it accordingly. You will get all the Redis related variables values from your Redis enterprise DB configuration page.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

PORT=
REDIS_DB_URL=
REDIS_DB_USER=
REDIS_DB_PASS=
TOKENEXPIRATIONTIME=
JWTSECRET=



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

&lt;/div&gt;
&lt;p&gt;Now, start the server and then test your newly created authentication flow via Postman or any HTTP client of your choice. Create a few users and log in with your credentials.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0hmtekjy7fvhhg7q93sr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0hmtekjy7fvhhg7q93sr.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Building the event module
&lt;/h3&gt;

&lt;p&gt;The event module is the heart of this application and where the full power of the Redis database comes to bear. Before now, it’s really a big hassle trying to perform the equivalent of an SQL-like queries in Redis. One has to follow or device many unconventional approaches to search saved data beyond just searching by the key.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The RediSearch module since its development has been a game changer in this regard. It’s now much easier to perform various searches e.g. fulltext search, aggregate search results, sort and so much more. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is why we added the RediSearch module to our database while setting it up to be able to search events by various parameters so let’s get to it.&lt;/p&gt;

&lt;p&gt;The first thing to do is model the data that we will be performing search on and creating an index out of it. The better your index, the more performant your search will be.&lt;/p&gt;
&lt;h4&gt;
  
  
  Modeling the data and creating the index
&lt;/h4&gt;

&lt;p&gt;Create a new directory under &lt;em&gt;"src"&lt;/em&gt; called repository and in it, create a new file named &lt;em&gt;event.js&lt;/em&gt; the paste the following code into that file.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;In the code above, again, we imported the redis connection that was created in the db directory since that is our gateway to the Redis enterprise database. Now let’s talk about the different “redis-om” data types assigned to various fields. Here, there are four major data types we are working with which are string, text, date, and point.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;String&lt;/strong&gt;: The string data type normally should be assigned to any field that we want to perform exact match search on e.g fields with definite list of values for example category, genre, type, etc. This type maps to &lt;strong&gt;&lt;em&gt;TAG&lt;/em&gt;&lt;/strong&gt; in the underlying RediSearch type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text&lt;/strong&gt;: The major difference between the string and text field is that you can perform full text search on the text field which is not possible on a field designated as string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Point&lt;/strong&gt;: This field is used for storing location value in terms of longitude and latitude so if you intend to perform location based search, then you should use the point type on such field. This type maps to &lt;strong&gt;&lt;em&gt;GEO&lt;/em&gt;&lt;/strong&gt; in the underlying RediSearch type&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date&lt;/strong&gt; field is exactly what it means, working with dates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes, we want to see the most recent entries first and vice-versa, to do that, we need to mark the field as “sortable” which will help us sort our search results based on various conditions.&lt;br&gt;
You can read more about how schema/entities are created in redis-om &lt;a href="https://github.com/redis/redis-om-node#-define-an-entity-and-a-schema" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that there is one field in the schema &lt;strong&gt;"dataStructure"&lt;/strong&gt; with the value &lt;strong&gt;"HASH"&lt;/strong&gt;, this is telling Redis that we want to use the hash data structure for the schema. This is necessary because by default redis-om uses the &lt;em&gt;RedisJSON&lt;/em&gt; data structure and because we did not add that to our database while setting it up, it will throw an error. &lt;/p&gt;

&lt;p&gt;RedisJSON is another Redis module which could be better suited for storing JSON-like data like the one we have here but I’ve decided to use the HASH data structure just to focus more on the RediSearch module in this article. More on that here&lt;/p&gt;

&lt;p&gt;Finally, to create the index, you’ll call the createIndex() method on the schema repository.&lt;/p&gt;

&lt;p&gt;Now that we have every bit of the puzzle needed to complete this amazing app, let’s bring them together.&lt;/p&gt;
&lt;h4&gt;
  
  
  Building the event management platform on Redis
&lt;/h4&gt;

&lt;p&gt;In the controllers directory, create a file and name it &lt;em&gt;"event.js"&lt;/em&gt; and paste the following code in the file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Not much is going on in the "createEvent()" controller function, we are just calling the "createAndSave()" method on our exported event schema repository after passing the user event object into it.&lt;/p&gt;

&lt;p&gt;The real power of the RediSearch module started becoming evident from the "getAllEvents()" controller function. Here, we are able to use some of the handy methods exposed by the redis-om library to fetch all events, sort them to ensure that the most recent event show up first and also paginate. Now, isn’t that sleek? 😉.&lt;/p&gt;

&lt;p&gt;In an SQL based database, this query will look something like the following&lt;br&gt;
&lt;code&gt;SELECT * FROM table_name ORDER BY field DESC LIMIT limit OFFSET offset;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All of these aren’t an easy feat to do in Redis before the advent of the Redisearch module. Notice that we called the “sortDescending” method on the createdAt field which was why we marked it as sortable while defining our schema.&lt;br&gt;
This is why I say that how performant your search will be will dependent on good your index is.&lt;/p&gt;

&lt;p&gt;Another interesting controller function here is the "getEventsNearMe()" function. This uses the location given by the user and the distance they set or search within a 10 Kilometer radius if distance isn’t provided. We are able to do this because we marked the "locationPoint" field as "point" while creating our schema.&lt;/p&gt;

&lt;p&gt;Lastly there is the "searchEvents" controller function that searches events based on two conditions, the category of the event and title. Of course if we are searching events by the categories it is easier to search the category as a whole e.g conference, concert etc. But if we intend to search events by their title, it wouldn’t make sense to expect our users to memorize the exact title of events. &lt;/p&gt;

&lt;p&gt;This is the reason why we designated the title field with the "text" data type so that we can perform full text search on it which means that, if users remember a particular phrase in the title of the event they are looking for, they can search by that phrase and the various events with similar phrase will get returned to them.&lt;/p&gt;

&lt;p&gt;Ok, enough of that and let’s complete the other parts of the application. You would have noticed that we had some dependencies used in the event controller file that doesn’t currently exist, so let’s plug in the missing pieces.&lt;/p&gt;

&lt;p&gt;Create a new file called "pagination.js" in the utils directory and copy and paste the following code into it. This is just to handle our result pagination.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Remember the middleware directory that was created earlier? now create a new file in that directory called index.js and paste the following code into the file. This is what will ensure that only the right users have access to various parts of the application.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s now plug our controller to appropriate routes so that users request will be handled in the correct manner. Create a new file in the routes directory called event.js and paste the following code into it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Finally, let us make the presence of the event route known to our server by importing the event route module in the app.js file. By now, your app.js file should look like the one below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now that we are done, let’s test out the various endpoints for the event management application. So, fire up your Postman or any other HTTP client that you’re using and create some events, fetch all events, and search events using various parameters. Below are a few of the screenshot of my personal tests.&lt;/p&gt;

&lt;p&gt;I suggest that you open up your RedisInsight to visualize some of the data that you’ve been saving all the while.&lt;/p&gt;

&lt;p&gt;The complete backend code can be found in this &lt;a href="https://github.com/iMichaelOwolabi/event-manager" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the frontend of our event management app using React.
&lt;/h3&gt;

&lt;p&gt;The frontend code for the event manager application can be found &lt;a href="https://github.com/iMichaelOwolabi/event-manager-front" rel="noopener noreferrer"&gt;here&lt;/a&gt;, just clone the repository, follow the setup guide and start both the server and the frontend app. You should be able to see some of the events that you’ve created. Perform some searches using various parameters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbd7iwydmnojnt5nlm4j5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbd7iwydmnojnt5nlm4j5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s still so much that can be done to improve this app as listed below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search events by date range&lt;/li&gt;
&lt;li&gt;Search events by country (I know we don’t have a country field and you can just update the schema with that. Don’t worry about your index, it will be rebuilt when you restart your server)&lt;/li&gt;
&lt;li&gt;Modify event information e.g. the date of the event&lt;/li&gt;
&lt;li&gt;Delete event...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congratulations for getting this far. You have just built your event management application fully on the Redis database 👏🏼.&lt;/p&gt;

&lt;p&gt;Do let me know what you feel in the comment section.&lt;/p&gt;

&lt;p&gt;Below are some helpful links if you’re looking to explore Redis beyond what is in the context of this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.redis.com/?utm_campaign=write_for_redis" rel="noopener noreferrer"&gt;Redis Developer Hub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://redis.info/3Ga9YII" rel="noopener noreferrer"&gt;More on Redis Enterprise&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/redis" rel="noopener noreferrer"&gt;Redis Discord&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Caveat
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Redis-om is still in the preview stage and it’s not stable enough to be used in production at the time of writing this article. You can use other Redis clients if you intend to use Redis in production you can choose from other recommended clients &lt;a href="https://redis.io/docs/clients/#nodejs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;This post is in collaboration with Redis.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you enjoyed working with us like we enjoyed working with you and want to continue writing for us, we’re now accepting applications for more blogs. You can apply &lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSd_yuc3-l6ojw_W4N8H3ueLe1ZBcrAWUawi4CPIlwIpXqF7QA/viewform" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>redis</category>
      <category>redisearch</category>
      <category>node</category>
      <category>react</category>
    </item>
    <item>
      <title>This is why your Node.js application is slow</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Tue, 08 Feb 2022 12:13:22 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/this-is-why-your-nodejs-application-is-slow-206j</link>
      <guid>https://dev.to/imichaelowolabi/this-is-why-your-nodejs-application-is-slow-206j</guid>
      <description>&lt;p&gt;Many performance-related issues in Node.js applications have to do with how promises are implemented. Yes, you read that right. How you implemented promise in your Node.js app is most likely the culprit for how slow your app has become 🙈.&lt;/p&gt;

&lt;p&gt;Promise is one of the popular ways of implementing asynchronous programming in Node.js which is a really good improvement over callbacks. First I’ll like us to get the literal meaning of promise outside of Node.js:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;a statement that tells someone that you will definitely do or not do something&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.oxfordlearnersdictionaries.com/definition/american_english/promise_2" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The keyword in the definition above is “WILL” which signifies sometime in the future. It simply means that a promise is an assurance of something that will happen in the future.&lt;/p&gt;

&lt;p&gt;This is the exact concept of promise in Node.js which denotes that when we try to perform some operations whose results we cannot get immediately, we instead get an “assurance” of the result that will be available sometime later. The important question then is “while we wait for the promise to get fulfilled, is it ideal to “idly” wait and not execute other parts of the program, especially the ones whose results can be readily available or not?”&lt;/p&gt;

&lt;p&gt;The answer to the question above will inform how you would work with almost inevitable promises in various parts of your applications.&lt;/p&gt;

&lt;p&gt;There are many ways of working with promises in Node.js but async/await is a really nifty approach that many have grown to love over the years since its introduction. The truth is lots of &lt;em&gt;.then&lt;/em&gt; in promise chaining is not very easy to keep track of when they grow to a considerable length (see example &lt;a href="https://javascript.info/promise-chaining" rel="noopener noreferrer"&gt;here&lt;/a&gt;) neither is callback (Callback hell &lt;a href="http://callbackhell.com/" rel="noopener noreferrer"&gt;see here&lt;/a&gt;). So it’s understandable why many will choose the more convenient and cleaner async/await but which sometimes can be injurious to the overall performance of your application when not applied correctly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;async/await &amp;lt;--&amp;gt; async/ablock 🤐&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  So, what is the problem with async/await? You ask.
&lt;/h3&gt;

&lt;p&gt;The simple problem with it is that it is capable of slowing down your application greatly when not correctly used. Whenever a promise is marked with await in an async function, what you are saying is that, until the promise has resolved,  the following code or code blocks in the function shouldn’t be executed which in itself is not a bad thing.&lt;/p&gt;

&lt;p&gt;However, it becomes a problem when the code that follows can in fact be executed while waiting for the promise to get resolved because they are not dependent on the result of the resolved promise. Let’s consider the code below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;br&gt;
&lt;a href="https://media.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%2Fo6j7p4mmbs3mjsjvbjq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fo6j7p4mmbs3mjsjvbjq6.png" alt="Blocking await"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the code snippet above, even though the two awaits were unrelated they still block each other. The second promise did have to wait for the first one to resolve before it starts which means it will take double the time for all the promises to get resolved.&lt;/p&gt;

&lt;p&gt;Below is a better to handle the promises such that they don’t block each other while still using your lovely await 😉&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;br&gt;
&lt;a href="https://media.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%2F1g2ffokdomsxtgfhk87l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1g2ffokdomsxtgfhk87l.png" alt="Non-blocking await"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we used await with promise.all to ensure that the two promises got executed in parallel which means instead of taking double the time as we had in the blocking example, the two promises got resolved together in ~2 seconds which was half the time of the blocking example. Now isn’t that good?&lt;/p&gt;

&lt;p&gt;What to note here is that👇🏼&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;unrelated promises shouldn’t block each other&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Does this mean related/dependent promises should block each other?
&lt;/h3&gt;

&lt;p&gt;No! Depending on the case but most times, even dependent promises can be implemented in a way that ensures they are not blocking or the blocking gets reduced to the barest minimum for improved performance. Once again, let’s consider yet another example of this scenario:&lt;/p&gt;

&lt;p&gt;Let’s say in an employee management system, you want to get the list of employees alongside their next of kin information.&lt;br&gt;
In such a system, we first need to get the employee information and use that to find their next of kin which means we will have a dependent promise situation. Let us look at both the inefficient and a more efficient way to do this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Below is the actual logic that determines how to work with the employee and next of kin data in the DB. This is where all the good and bad choices will matter:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;br&gt;
&lt;a href="https://media.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%2Fxh5su731gntv1hyp6a2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxh5su731gntv1hyp6a2k.png" alt="Await in loop implication"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the second asynchronous operation had to wait for the first to complete before starting which is fine, but the problem is in using await inside the loop which every asynchronous operation (getting next of kin) had to wait for the one before it 😳 This is bad. Don’t do it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One of the cases of bad use of async/await is inside a loop.&lt;br&gt;
Majority of the time you can and should avoid it,&lt;br&gt;
at least if the performance of your application and the&lt;br&gt;
time of your user matters to you then you should.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let's look at the better approach below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;br&gt;
&lt;a href="https://media.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%2Fag4elbl8mqbdx1xjnxj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fag4elbl8mqbdx1xjnxj8.png" alt="parallel promise execution result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that in the code snippet above since the second operation is dependent on the result of the first one and there are no other synchronous operations that will be blocked, as a result, we waited until all employee records are available before starting the next operation that gets their next of kin information.&lt;/p&gt;

&lt;p&gt;However, instead of each iteration of promise to wait on the one before it, the promises were stored and executed in parallel which saves immense execution time than the first approach, and the entire operation finished in ~2 seconds as opposed to the first blocking example that took ~6 seconds to complete execution.&lt;/p&gt;
&lt;h3&gt;
  
  
  Blocking the event loop 🚫
&lt;/h3&gt;

&lt;p&gt;Another reason your Node.js application may be performing poorly is that you could be blocking the event loop in your code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Event loop is responsible for executing actual JavaScript and non-blocking I/O in Node.js&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can read more about the event loop &lt;a href="https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We say that the event loop is blocked when it is not able to continue executing JavaScript while an operation that does not require the event loop (i.e non-JavaScript operation) is being processed e.g reading a file synchronously.&lt;/p&gt;

&lt;p&gt;Let's consider the example below:&lt;br&gt;
Assuming that in your application you need to work with countries and you have a list of countries as an external CSV file which you need to access in your code. In the code snippet below, the file reading operation blocks the event loop and ultimately affects the application’s throughput and performance because &lt;strong&gt;&lt;em&gt;until the file reading operation completes, nothing else gets executed&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fj7urrhc88id2ckyznqpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fj7urrhc88id2ckyznqpw.png" alt="Event loop blocking file reading result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s consider a better way this can be done in a way that it doesn’t block.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Result screenshot&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5scez7xvqk7crmdt5tk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5scez7xvqk7crmdt5tk1.png" alt="Event loop non-blocking file reading result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the actual reading of the file is an I/O operation that  does not require the event loop, this operation shouldn’t block and that is what is done here as the event loop is freed up to execute other parts of the application until the result of the file reading operation becomes available.&lt;/p&gt;

&lt;p&gt;The code snippet above uses callback which is just another method of implementing asynchronous programming in Node.js. This can be easily converted to promise so that you can use your lovely async/await for the same. One way of doing that will be to wrap the file reading operation in a promise and make the returned value a promise.&lt;/p&gt;

&lt;p&gt;There are definitely more reasons why your Node applications may perform poorly in terms of performance but these are the more common ones I have seen. You are welcome to share more insights in the comment section.&lt;/p&gt;

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

&lt;p&gt;The key things to remember regardless of which approach you chose to use when working with promises in Node.js is to ensure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unrelated promises do not block each other.&lt;/li&gt;
&lt;li&gt;Non dependent promises are executed in parallel and not sequentially.&lt;/li&gt;
&lt;li&gt;Don't use await inside a loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regarding the event loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whatever you do, ensure that the event loop isn’t blocked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can keep these in mind, you will be intentional about taking better decisions on which approach to use so that the performance of your application doesn’t suffer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading:
&lt;/h3&gt;

&lt;p&gt;This article is majorly focused on a single approach to working with promises and its implications.&lt;br&gt;
There are other ways/things to consider to achieve the same or sometimes better result when working with promises in Node.js which I encourage you to read up on in the links below:&lt;br&gt;
&lt;a href="https://www.nearform.com/blog/broked-promises-james-snell-tech-talk-video/" rel="noopener noreferrer"&gt;Broken Promises&lt;/a&gt; - James Snell&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/en/docs/guides/dont-block-the-event-loop/" rel="noopener noreferrer"&gt;Don't block the event loop&lt;/a&gt; - A Node.js guide on never blocking the event loop.&lt;/p&gt;

&lt;p&gt;N:B&lt;br&gt;
If you know of other ways of making asynchronous programming a bliss in Node.js, please do share in the comment section.&lt;/p&gt;

</description>
      <category>node</category>
      <category>promise</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>KYC for Software Developers</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Fri, 30 Apr 2021 21:50:33 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/kyc-for-software-developers-42k7</link>
      <guid>https://dev.to/imichaelowolabi/kyc-for-software-developers-42k7</guid>
      <description>&lt;p&gt;KYC which stands for “know your customer” 🔎 is a concept popularized by the finance industry which was introduced to prevent/reduce financial crimes. KYC has helped a great deal in combating various financial crimes but it has also been a mechanism businesses over the years leveraged to serve their customers right since they have done due diligence on them.&lt;/p&gt;

&lt;p&gt;The latter part of the benefits of KYC as explained above is what we will focus on in this article as Software Developers. But first, what exactly does KYC mean for Software Developers?&lt;/p&gt;

&lt;h3&gt;
  
  
  KYC for Software Developers - What it means
&lt;/h3&gt;

&lt;p&gt;Just as we have it in the finance sector, KYC is simply knowing who our customers/clients are as Software Developers in order to be able to serve them well. I’m sure you must have heard the saying “customer is king” 👑.&lt;/p&gt;

&lt;p&gt;The truth is, we all have customers even as Software Developers, and wouldn’t it be great that we get to know our customers well enough in order to know how best to delight them?&lt;br&gt;
So, the question is that “As a Software Developer, do you really know your customers”?&lt;/p&gt;

&lt;h3&gt;
  
  
  Do you know your customers?
&lt;/h3&gt;

&lt;p&gt;Firstly, who is a customer? According to this &lt;a href="https://en.wikipedia.org/wiki/Customer" rel="noopener noreferrer"&gt;Wikipedia definition&lt;/a&gt;, a customer is “The recipient of a good, service, product or an idea”. Using this definition in the premise of software development as developers, it means that whoever we render software service, product, or an idea to is our customer.&lt;/p&gt;

&lt;p&gt;In this article, we are going to only explore KYC as it relates to 2 categories of developers.&lt;br&gt;
1 Backend Developer&lt;br&gt;
2 Frontend Developer (Mobile and Web)&lt;/p&gt;

&lt;h3&gt;
  
  
  Caveat ✋🏼
&lt;/h3&gt;

&lt;p&gt;The end-user of the product is the ultimate customer of all Software Developers regardless of which side of the technology you work in. If you don’t put the end-user in mind while developing the product, you’re most likely just setting yourself and the team up for failure.&lt;/p&gt;

&lt;p&gt;There is no product without the end-user, it is as simple as that so effort should be put into knowing them so as to develop a great product that meets their needs/wants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customers of a Backend Developer
&lt;/h3&gt;

&lt;p&gt;The following people are the ones you should hope to delight as you work on the server-side of the product/application.&lt;/p&gt;

&lt;p&gt;As a backend developer your customers are primarily the frontend developer, the product manager, and then the end-user of the product. Let's talk about how that is below 👇🏼&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend developer (Mobile and Web)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the frontend developer is the one who will be consuming your carefully crafted APIs and present your work in a more friendly way to the end-user, as a backend developer, you need to develop the habit of delighting the frontend developers on your team.&lt;/p&gt;

&lt;p&gt;Putting the frontend developer in consideration when developing applications can actually help in developing better solutions on the server-side of things.&lt;/p&gt;

&lt;p&gt;How well you satisfy your frontend developer(s) will have a direct impact on the end-user of the product. For example, if your endpoints have terrible response times, you will most likely frustrate the frontend person especially when some of these endpoints are ones with data that change very often.&lt;/p&gt;

&lt;p&gt;In this case, even the end-user will be affected and there will be nothing the frontend developer can do about it. So, invest time in knowing them so that you can delight them 😉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnawyrqgvbk5fof1j8elc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnawyrqgvbk5fof1j8elc.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giphy.com/gifs/blackluckfilm-angry-huh-xUOxfhdEwk5hITHOog" rel="noopener noreferrer"&gt;image source&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Equally, the product manager is the direct customer of a backend developer and you will need to deliver in a way to keep them satisfied as well. To put the product manager in mind is to carefully examine and understand the product requirements and vision of a product which in turn will lead to churning out better software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customers of the Frontend Developer (Mobile/Web)
&lt;/h3&gt;

&lt;p&gt;As the frontend developer, you’re the closest person to the end-user and they are your number one customer alongside the product manager and the backend developer so you should take your time to know them and work to delight them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since you’re the gateway into the application/product and like they say, “the first impression lasts longer”. Whatever experience you leave the user with during their first encounter with the product can be a determinant as to whether or not they will continue using the product so you should try your best to make sure you leave them delighted as much as possible.&lt;/p&gt;

&lt;p&gt;Make sure you always advocate for the end-user at every available opportunity because they are the most important entity to the product and you are the one interfacing directly with them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Backend Developer&lt;br&gt;
Just as you are a customer to the backend developer so is the backend developer a customer to you. The relationship between you two is bi-directional so you should try to make their life easier the same way they should yours.&lt;br&gt;
A good synergy must exist between you two to create an amazing product that your users will love.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Product Manager&lt;br&gt;
Yes, the product manager is your customer and not your enemy as the frontend developer. Knowing your product manager well can help you understand their vision beyond the written requirements for the product which will in turn help in crafting out a better solution that will make everyone happy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;“Customer is king”, investing in knowing them will mean that you’ll be able to serve them in ways that keep them delighted and, a delighted customer is a loyal customer who will continue to sing your praise without paying them to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjt1gwupf2r34syqjrwdu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjt1gwupf2r34syqjrwdu.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giphy.com/gifs/hulu-snl-saturday-night-live-nbc-l0MYNtfxWsYtZN852" rel="noopener noreferrer"&gt;image source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though in the software world, the word “customer” often refers to the end-user but the truth is in order to delight the end-user by our application via the code we write, we need to keep our internal customers delighted as well failure of which will have a bad ripple effect on our end user.&lt;/p&gt;

&lt;p&gt;So, I’m putting it to you as a Software Developer reading this that you should endeavor to know exactly who your customers are both internal and external, and strive as you write your code to keep them delighted.&lt;/p&gt;

</description>
      <category>kyc</category>
      <category>software</category>
      <category>developers</category>
      <category>tips</category>
    </item>
    <item>
      <title>What case should your API request/response be?</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Thu, 11 Mar 2021 20:11:18 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/what-case-should-your-api-request-response-be-ggo</link>
      <guid>https://dev.to/imichaelowolabi/what-case-should-your-api-request-response-be-ggo</guid>
      <description>&lt;p&gt;As a backend developer who writes APIs from time to time, I’ve always wondered if I am delighting my customers who in most cases are other developers when interacting with my APIs.&lt;br&gt;
Thoughts like these always make me think about lots of things from performance, speed, etc. But very recently I started to think about how the final result of my APIs are formatted and how my supposed customers would prefer to have it. This, most times is not top of mind when writing APIs.&lt;/p&gt;

&lt;p&gt;The programming language we use for a particular application usually determines how we structure/format strings. Generally, there are about 4 popular cases for naming things in different programming languages which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Camel case - JavaScript e.g firstName&lt;/li&gt;
&lt;li&gt;Pascal case - Pascal e.g FirstName&lt;/li&gt;
&lt;li&gt;Snake case - Python e.g first_name&lt;/li&gt;
&lt;li&gt;Kebab case - Lisp e.g first-name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the question is:&lt;br&gt;
what should be the perfect case for the request/response object of my API?&lt;br&gt;
What case do other developers using my API expect to see while interacting with my API?&lt;br&gt;
Should the language I code in be the determinant of how my API request/response object case will be formatted?&lt;/p&gt;

&lt;p&gt;These thoughts took me on a journey of API exploration. I don't think there is a better way to get an answer to this question than examining the documentation of some existing brands. Below is what I discovered👇🏼&lt;/p&gt;

&lt;h3&gt;
  
  
  What I’ve seen so far 👀
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stripe.com/about" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt;:&lt;br&gt;
Stripe uses snake case for their request/response object across their APIs regardless of the language used. Take a look at their documentation page &lt;a href="https://stripe.com/docs/api" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.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%2Ftvr29f97ho3al7px1nmq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftvr29f97ho3al7px1nmq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.monnify.com/" rel="noopener noreferrer"&gt;Monnify&lt;/a&gt;:&lt;br&gt;
Monnify is a brand of TeamApt, a Fintech company just like Stripe based in Lagos, Nigeria. Monnify uses camel case for the request/response object of their APIs. You can have a look at their documentation &lt;a href="https://docs.teamapt.com/display/MON/General+Integration+Docs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fa2kzlrysvmyipxi3amrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fa2kzlrysvmyipxi3amrd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;br&gt;
Twitter mostly uses snake case for the request/response object of their API doc at least the parts I’ve worked with. You can also take a sneak peek at their doc &lt;a href="https://developer.twitter.com/en/docs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffuwaxouwz0ha7rajigck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffuwaxouwz0ha7rajigck.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.eventbrite.com/about/" rel="noopener noreferrer"&gt;Eventbrite&lt;/a&gt;&lt;br&gt;
Eventbrite just like Stripe uses snake case for their request/response API object. You can take a look at their doc &lt;a href="https://www.eventbrite.com/platform/docs/introduction" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fo1yzlclde1h068zfzrsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fo1yzlclde1h068zfzrsj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ng.getcarbon.co/about.html" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;&lt;br&gt;
Carbon API documentation, different from every other one we have looked at uses a mix of snake case and camel case for their request/response object. This is the first time I am seeing anything like this. You can also take a look at their doc &lt;a href="https://sme.getcarbon.co/developers#identity-verification-overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgcrvtm75wyqomqoi1out.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgcrvtm75wyqomqoi1out.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I must confess that I have seen more JSON-based API request/response object for many documentations in snake_case than any other case but I have also seen a fair share in other cases especially camelCase. I have equally written some endpoints that uses snake case and camel case in various APIs as well but I will also like to have your opinion on this subject.&lt;/p&gt;

&lt;h3&gt;
  
  
  P.S.
&lt;/h3&gt;

&lt;p&gt;This is a very short article on a very focused topic through which I hope to drive meaningful conversation so do not hesitate to share your opinion on the topic in the comment section below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Developers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a frontend developer (mobile or web) what case do you expect to consume your API in or what is your most preferred case? &lt;/li&gt;
&lt;li&gt;Do you use any library to convert your request/response object to your preferred case of choice should the API not be in that case?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Backend Developers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the language you write in determine what case your API request-response object will be?&lt;/li&gt;
&lt;li&gt;Do you use any library to unify your API request/response case irrespective of the language? Care to share?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>case</category>
      <category>discuss</category>
      <category>backend</category>
    </item>
    <item>
      <title>Ask questions, ask lots of it</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Mon, 28 Sep 2020 07:23:44 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/ask-questions-ask-lots-of-it-147p</link>
      <guid>https://dev.to/imichaelowolabi/ask-questions-ask-lots-of-it-147p</guid>
      <description>&lt;p&gt;If there is one thing that software development has taught well, it is the fact that whatever you don’t know, you do not know. You cannot brag or pretend your way into building or fixing stuff in this field. You will end up ignorant and obsolete especially in this tech world if you’re not willing to sit and learn or humble enough to ask for guidance.&lt;/p&gt;

&lt;p&gt;Contrary to what many think, it’s actually the smart people that ask questions. The unintelligent ones will never realize the need to learn what they need to learn in order to achieve their desired result. Some feel too big to ask for help while others are more concerned about what others will think than their own success.&lt;br&gt;
Wake up from your slumber and don’t spend years on what should take you days to accomplish because you have refused to ask questions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The smart ones ask when they don’t know. And, sometimes, when they do.” - Malcolm Forbes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why should you ask questions?
&lt;/h2&gt;

&lt;p&gt;Apparently, if you’re the one who doesn’t like to ask questions then you might be in the wrong field because things change very fast when it comes to software development or tech in general and you cannot afford to keep struggling in silence while the world leaves you behind when you can easily ask the next person for help and save valuable time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Saves you valuable time
&lt;/h3&gt;

&lt;p&gt;Simply opening your mouth to ask questions can save you hours, days, or even weeks of frustration. There have been times when I’ve spent hours trying to fix a particular bug and kept on wondering why my code wasn’t working as it should, but when I call on someone else to help take a look, we got the issue resolved in less than 5 minutes. Now, I could have saved myself lots of valuable time if I had asked for help earlier.&lt;/p&gt;

&lt;p&gt;Another way that asking questions can save you valuable time especially if you’re a beginner is that you will not spend your limited time learning what is irrelevant or outdated. There are tons of materials on the Internet today, but not all materials are beneficial to you when trying to learn or grow as a software developer in 2020 so save your self the stress and ask questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Saves you from making stupid mistakes
&lt;/h3&gt;

&lt;p&gt;Mistakes are definitely inevitable and while we all make mistakes from time to time, you should not be among the ones who make stupid/avoidable mistakes on a recurring basis only because you have refused to ask questions. Majority if not all of the things you will ever try to do as a software developer have been done before so if only you can ask for help from those around you will not make avoidable mistakes. This is why standard/best practices were developed so that you will not make the same mistakes as the people before you. When you ask questions, you are literally standing on the shoulders of giants and thereby you will not make foolish mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Broadens your knowledge
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“Questions and not answers create knowledge”&lt;/em&gt; that was the inscription on one of my faculty students association shirts while in the university. I have always thought about this statement from the first time I saw it on that shirt and I have come to realize that it is true.&lt;br&gt;
It is indeed our curiosity for knowledge that always prompts us to ask difficult questions or any question at all and by doing that we unlock an enormous wealth of knowledge. When you ask questions, you learn new things or learn a new way of doing the same thing better and thereby broaden your scope of knowledge very fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everyone (Experts, Colleagues, Mentors, Friends) has been saying this for too long
&lt;/h3&gt;

&lt;p&gt;Ok ok enough of all that! Maybe you’re wondering what I am talking about and still not convinced that asking questions can give you an advantage in this field, that’s fine. You don’t have to take my word for it just know that some of those we call friends, colleagues, and look up to in this field have been saying this same thing for a very long time.&lt;br&gt;
So, I’ve done you the favor of curating some of their tweets, just take a look at the gallery of tweets screenshots below and see why it is important for you to ask questions in their own words.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg4qbb2oz7hya9e0obou1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg4qbb2oz7hya9e0obou1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fluqoxagblt766rhby6xm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fluqoxagblt766rhby6xm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9cnh4sysbbp7ap76irsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9cnh4sysbbp7ap76irsz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdhyx52smznwoepjeqp46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdhyx52smznwoepjeqp46.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4zgehiy4l0rcm94o7bm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4zgehiy4l0rcm94o7bm5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3vewfmq33syb2iej4p5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3vewfmq33syb2iej4p5o.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvxs1f02r6752kd3hhnp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvxs1f02r6752kd3hhnp3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbtuewob61mp9rvrzvbhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbtuewob61mp9rvrzvbhv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh9k2cbf1eq59bm7tkb6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fh9k2cbf1eq59bm7tkb6u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc9wf1a5f60rbwknvjkri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc9wf1a5f60rbwknvjkri.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcm85upnsnzy3cvyrokyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcm85upnsnzy3cvyrokyr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff83fgr4n244rlivfgl4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff83fgr4n244rlivfgl4c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxe719aicn2ahwy338l9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxe719aicn2ahwy338l9k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can do to help
&lt;/h2&gt;

&lt;p&gt;Different people have different reasons why they choose not to ask questions but the majority are just more concerned about what others will think or say about them asking questions. While this shouldn’t be an excuse per se, it is a fact that we can create an enabling environment where individuals feel free to ask questions without being labeled or made to feel as though they are dumb.&lt;/p&gt;

&lt;p&gt;In order to achieve this we must all ensure that when people ask questions, we don’t judge them either by our words/actions and that we don’t put people down directly or indirectly for asking questions but rather encourage and create that enabling environment where others are free to ask.&lt;/p&gt;

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

&lt;p&gt;You have limited time and there is so much to learn as far as software development or tech in general is concerned. In fact, it is impossible for one person to know it all but the only chance you have not to waste your limited valuable time and make avoidable mistakes is by asking questions. Be humble enough to admit things you don’t know and summon the courage to ask for help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjf85ufam35621qhzgwrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjf85ufam35621qhzgwrs.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My challenge to you after reading this is to imbibe that culture of asking questions and you will be surprised how much people are willing to help only if you ask._&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you like this article, kindly share with your network so that others can benefit as well. I can also be reached on Twitter &lt;a href="https://twitter.com/iMichaelOwolabi" rel="noopener noreferrer"&gt;@iMichaelOwolabi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>questions</category>
      <category>codenewbie</category>
      <category>sofware</category>
      <category>career</category>
    </item>
    <item>
      <title>Redis Data Structure Part 1</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Sat, 01 Aug 2020 13:56:31 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/redis-data-structure-part-1-5ggn</link>
      <guid>https://dev.to/imichaelowolabi/redis-data-structure-part-1-5ggn</guid>
      <description>&lt;p&gt;One of the outstanding features of Redis that make it is so loved among the developer community is the speed at which various operations are carried in a Redis database. So many things contribute to this efficiency in speed but one thing at the core of Redis regardless of how one chooses to look at it is its robust data structure.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The performance of every application that uses Redis is directly tied to how the application implements the various Redis data structures&lt;strong&gt;.&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this article, we are going to examine various data structures in Redis so as to give us insight on when it’s best to use which of the available data structures so that we can take full advantage of all the goodies Redis has to offer in our applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To get the most out of this article, I strongly recommend that you get a copy of Redis for your computer &lt;a href="https://redis.io/download" rel="noopener noreferrer"&gt;here&lt;/a&gt; OR use the online Redis server at &lt;a href="https://try.redis.io/" rel="noopener noreferrer"&gt;https://try.redis.io/&lt;/a&gt; to try out simple commands that will be used in the course of this article.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of Redis&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Redis Data Structures
&lt;/h2&gt;

&lt;p&gt;Below, we will examine a few of the data types that we have in Redis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To get the type of value a key holds in Redis you can use the type command to do that as shown below.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;type key1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  String
&lt;/h3&gt;

&lt;p&gt;This is the base and simplest data structure in Redis that can be associated with a key. &lt;strong&gt;Strings in Redis are binary safe&lt;/strong&gt; and support polymorphism which means that a string key can be modified to hold binary, integer, or even floating-point values. String in Redis has a limit of 512 Mb data size that can be stored in them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common commands and operations in Redis String
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SET&lt;/strong&gt;&lt;br&gt;
This is the command used to set or declare a Redis key to hold a string data type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set day Saturday
set name “Michael Owolabi”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I quote the value in the second example. We use the quote to group string that contains spaces in them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64r7366ofqjtawax3857.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64r7366ofqjtawax3857.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;br&gt;
This can be used to retrieve the value stored in a string Redis key.&lt;br&gt;
Get name will return the value “Michael Owolabi” that was set earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn8gspb4035k0kc0d2l7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn8gspb4035k0kc0d2l7n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;INCR&lt;/strong&gt;&lt;br&gt;
This command is used to increment the value of a key by exactly one (1).&lt;br&gt;
This is possible if the actual value of the key is a number. Remember that we said Redis strings are binary-safe&lt;br&gt;
E.g.&lt;br&gt;
Set price 10&lt;br&gt;
Incr price&lt;br&gt;
Get price returns 11 because its value has been increased by one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx888jl3iimzkla0t8ata.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx888jl3iimzkla0t8ata.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full list and detailed explanation of various Redis String commands can be found &lt;a href="https://redis.io/commands#string" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Hashes
&lt;/h3&gt;

&lt;p&gt;A hash can be likened to objects in JavaScript or dictionary in Python or generally a JSON-like data type. It is like a mini key value stored within a Redis key.&lt;br&gt;
A hash can have as many field-value pairs as possible until the size limit of a hash is reached which is 232 - 1 field-value pairs (more than 4 billion).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Redis hash is good for storing JSON like data especially when we’ll be working with the individual fields in the hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Common commands and operations in Redis Hash
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;HMSET&lt;/strong&gt;&lt;br&gt;
This is used to set the field-value pair of a hash key in Redis&lt;br&gt;
e.g&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hmset user:1 firstname Michael lastname Owolabi sex Male&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This is the equivalent of a JSON structure like so:&lt;br&gt;
  &lt;strong&gt;{&lt;br&gt;
    "user:1": {&lt;br&gt;
      "firstname": "Michael",&lt;br&gt;
      "lastname": "Owolabi",&lt;br&gt;
      "sex": "Male"&lt;br&gt;
    }&lt;br&gt;
  }&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HGET&lt;/strong&gt;&lt;br&gt;
This is used to retrieve the value of a single field in a Redis hask key. For example, suppose we want get the firstname of user:1 we’ll use the hmget command as below:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hmget user:1 firstname&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fki1kjmktar66ih5htdve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fki1kjmktar66ih5htdve.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HGETALL&lt;/strong&gt;&lt;br&gt;
Instead of retrieving the individual field value, this command is used to retrieve the entire field value in a Redis hash key.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hgetall user:1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4x5bdjtj21neu74zqgk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4x5bdjtj21neu74zqgk3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full list and detailed explanation of various Redis hash commands can be found &lt;a href="https://redis.io/commands#hash" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  List
&lt;/h3&gt;

&lt;p&gt;This is an ordered collection of elements. Redis list is similar to Arrays in Ruby or JavaScript but differs in that it is implemented using a &lt;strong&gt;linked list&lt;/strong&gt;. Lists in Redis provides a simple way to implement queues, stacks, and other data structures that rely on ordering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common commands and operations in Redis List
&lt;/h3&gt;

&lt;p&gt;Unlike String and Hash in Redis, we don’t set a list instead we add or push elements on to the list&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LPUSH&lt;/strong&gt;&lt;br&gt;
This command is used to add an element to the list from the left. The &lt;strong&gt;L&lt;/strong&gt; in the command denotes that we want the new element(s) to be added to the list from the left.&lt;br&gt;
For example, suppose we want to add numbers from 1 through 10 to a number list from the left we do it by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lpush numbers 1 2 3 4 5 6 7 8 9 10&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg6bv614xj8c5s1fdf7fv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg6bv614xj8c5s1fdf7fv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since Redis list is zero-indexed, this means that element at index zero is 10 and the one at index nine is 1 because the elements are added from the left.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RPUSH&lt;/strong&gt;&lt;br&gt;
This is simply the opposite of the &lt;strong&gt;LPUSH&lt;/strong&gt; command. It adds elements to the array from the right instead of left as we have in LPUSH.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LRANGE&lt;/strong&gt;&lt;br&gt;
This is used to retrieve elements of the list using a range.&lt;br&gt;
To retrieve all the elements of a list specify the range from 0 to -1 which is the end of the list.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lrange numbers 0 -1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0gsyqbvxg1safg8mnjjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0gsyqbvxg1safg8mnjjf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get the element at a specified range or index specify the desired start and end index for elements you want to retrieve.&lt;br&gt;
Lrange numbers 0 0 will return the element at index zero (0).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLEN&lt;/strong&gt;&lt;br&gt;
This returns the length of the list.&lt;br&gt;
&lt;strong&gt;llen numbers&lt;/strong&gt; will return 10 since we have ten elements in the list.&lt;/p&gt;

&lt;p&gt;The full list and detailed explanation of various Redis List commands can be found &lt;a href="https://redis.io/commands#list" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;

&lt;p&gt;The set data structure in Redis is an &lt;strong&gt;unordered collection of unique strings&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Common commands and operations in Redis Set
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SADD&lt;/strong&gt;&lt;br&gt;
This command adds a new element or elements to the set e.g SADD cities Lagos Ibadan Accra will add three elements to the cities set.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This command only adds unique elements to the set, so for example, if we have repetitive numbers in an &lt;strong&gt;SADD&lt;/strong&gt; command, only one of the repeated numbers will be added to the set provided the number does not already exist in the set.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;SMEMBERS&lt;/strong&gt;&lt;br&gt;
This is used to retrieve all the elements of a set. This command is a total blocking command that will only release system resources until all the elements of the set have been retrieved.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;smembers cities&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fycr8u4hh5519atxpwr7m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fycr8u4hh5519atxpwr7m.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSCAN&lt;/strong&gt;&lt;br&gt;
This is also similar to &lt;strong&gt;SMEMBERS&lt;/strong&gt; command but only that this command runs iteratively or asynchronously without holding on to the system resources until all elements of the set have been retrieved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SCARD&lt;/strong&gt;&lt;br&gt;
This command is used to get the length of a set or just the total number of elements in a set.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scard cities&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SREM&lt;/strong&gt;&lt;br&gt;
This command is used to remove one or more elements from a set by the value.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SREM cities Accra&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6m7xqu2qzwyblc1glxt0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6m7xqu2qzwyblc1glxt0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full list and detailed explanation of various Redis Set commands can be found &lt;a href="https://redis.io/commands#set" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sorted Set
&lt;/h3&gt;

&lt;p&gt;This is basically a set only that a score is assigned to unique elements as a form of ordering so this means &lt;strong&gt;sorted set can be unofficially called an ordered set&lt;/strong&gt;.&lt;br&gt;
If two elements in a sorted set have the same score, then the tie is broken by the lexical order of the elements in the set. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt;&lt;br&gt;
The score associated with each element is a floating-point number so even if an integer value is provided as the score of an element, it will be automatically converted to a float.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Common commands and operations in Redis Sorted Set
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ZADD&lt;/strong&gt;&lt;br&gt;
This is used to add an element or elements along with their score to the set.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zadd student-score 98 Michael 82 Bisi 78 Hamdallah 85 Chigozie&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ZRANGE&lt;/strong&gt;&lt;br&gt;
This retrieves the elements of a sorted set&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zrange student-score 0 -1&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12jf902wqi4ermmj0jc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12jf902wqi4ermmj0jc3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ZRANGEBYSCORE&lt;/strong&gt;&lt;br&gt;
This returns elements of the set based on their score. For example, suppose we want to find the students who scored 90 and above we can do it by using the zrangbyscore command as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zrangebyscore student-score 90 +inf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can use -inf and +inf to denote a range especially when we don't know the bound of values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;ZSCORE&lt;/strong&gt;&lt;br&gt;
To get the score of an element in a sorted set, we use the zscore command. Suppose we want to get the score of Hamdallah in our sorted set we use the zscore command to achieve that as follows:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zscore student-score Hamdallah&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4idia2m78lfh0u3athkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4idia2m78lfh0u3athkh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full list and detailed explanation of various Redis Sorted Set commands can be found &lt;a href="https://redis.io/commands#sorted_set" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The knowledge of the Redis data structure is very vital to building a very efficient Redis based applications. Redis is fast and very efficient but with appropriate use and application of its data structures.&lt;/p&gt;

&lt;p&gt;If you find this article interesting, don’t forget to drop a ❤️ and use the comment section for any further comments.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Coding Convention: Why your team should adopt one quickly
</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Thu, 16 Jul 2020 16:21:30 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/coding-convention-why-your-team-should-adopt-one-quickly-1fhm</link>
      <guid>https://dev.to/imichaelowolabi/coding-convention-why-your-team-should-adopt-one-quickly-1fhm</guid>
      <description>&lt;p&gt;Your team needs to adopt its coding convention and do it quickly. This is a case of either do it or suffer the consequences.&lt;/p&gt;

&lt;p&gt;I am sure you have seen various arguments on issues like &lt;strong&gt;tab and space, snake_case and camelCase (DB related),  naming convention, etc&lt;/strong&gt; all these and many more are issues you will eventually have to address whether early on by adopting a team coding convention that will serve as a guide and ensure that everyone can sleep well at night or later on in the development stage where you have to do some tear-down and re-building because you have failed to address an important issue early on.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;What is coding convention?&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;These are sets of guidelines adopted by a software development team which enables the team to write consistent and easy to understand code by all team members. Usually, a team’s coding convention is a set of guidelines which is a document that guides not just how variables and methods should be named or the number of spaces that make a tab but which can also include the overall structure of the code and choice of design pattern used.&lt;/p&gt;

&lt;p&gt;Notice that I called it adopted because, in many cases, you will not have to define all these guidelines from scratch but rather use one or a mix of the existing conventions in your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;A note on best practice&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;The fact that various best practices at best are silent on some salient issues, then your team needs to develop exactly what is best for it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;Nothing is best about best practices if it does not benefit your team&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;Why your team should adopt one fast&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;Adopted team coding convention ensures that the team writes consistent code which means that there will be less back and forth among team members about code clarity.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qLa5YO6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gzzwd2tfnnixqa40vy7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qLa5YO6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gzzwd2tfnnixqa40vy7s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://vegaskid.net/2017/08/writing-good-code-101/"&gt;Image source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It helps new team members onboard quickly&lt;/strong&gt; because they can always have some sort of guide while looking at your codebase in a bid to understand it to be able to add valuable contributions thereby reducing the Turn around Time for delivery and increasing throughput.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It helps in code maintenance&lt;/strong&gt;. Having uniformity in codebase helps because everyone understands exactly where to find various pieces of code across the codebase and this helps greatly in maintenance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster debugging&lt;/strong&gt;. When you know where to find what, part of the problems is solved while debugging since you won’t have to start troubleshooting to know the exact location of various files/code in the codebase because there’s a certain way that your code is structured which is clear to all team members.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In general, adopting a team coding convention/guideline early on in the development process helps the team to work more efficiently than when each team members have their different styles which can lead to a problem when trying to integrate various parts of the codebase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;The chaos to expect if you fail to do so.&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;At best, you are the only developer in your team and you hope to leave as soon as the team starts to expand, by that, new developer team members won’t have your head 😂&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SQ_F9ONR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vmsbqt8y9y4b159t2arx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SQ_F9ONR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vmsbqt8y9y4b159t2arx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://xkcd.com/1926/"&gt;Image source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not having or adopting a particular coding convention for your team will lead to delay in development time because part of the time will be spent on arguing what is actually best from individual perspectives while in reality most of these things are really just based on preferences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging nightmare&lt;/strong&gt;&lt;br&gt;
Because you are not exactly sure how the other team member has structured his or her code, so much time can be wasted trying to find where various files are in order to be able to use them in debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;u&gt;Useful Tools&lt;/u&gt;
&lt;/h3&gt;

&lt;p&gt;Here are some nice open-source tools that can help in enforcing team coding convention. Although it may seem a little not convenient at first, it will be a great time saver in the long run.&lt;/p&gt;

&lt;h4&gt;
  
  
  Linters: ESLint (JavaScript)
&lt;/h4&gt;

&lt;p&gt;You can find various linters for your equivalent programming languages, they practically do the same thing. If you would like to know how linter works check &lt;a href="https://en.wikipedia.org/wiki/Lint_(software)"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Style guides: (Airbnb - JavaScript, PEP 8 - Python, Google Java style guide - Java)
&lt;/h4&gt;

&lt;p&gt;These are predefined guides that you can adopt for your team and integrate with your linter to the hard work of ensuring every line of code adheres to your adopted team’s coding convention.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;In conclusion, whether you choose to address the issue of coding convention early on in the development stage or you leave it to chance and at the mercy of individual team members, one thing is sure, you will still have to address it at some point in your development journey and one will be costly while doing it at the early stage will be beneficial to all.&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>codequality</category>
      <category>convention</category>
      <category>career</category>
      <category>software</category>
    </item>
    <item>
      <title>Your email could be your biggest career advancement enemy</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Tue, 30 Jun 2020 16:27:08 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/your-email-could-be-your-biggest-career-advancement-enemy-1h3g</link>
      <guid>https://dev.to/imichaelowolabi/your-email-could-be-your-biggest-career-advancement-enemy-1h3g</guid>
      <description>&lt;p&gt;My email is usually one of the first things I look through in the morning to check for anything new overnight. Recently, I was having not less than 15 unread emails in my inbox for about 5 consecutive days and I wasn’t feeling comfortable with it. All I do during these times is just to quickly scan through my mail for anything important and new and I could easily miss things this way.&lt;br&gt;
So, after about a week, I decided I was going to take the time out to correctly sort out my personal email, not just my inbox but my entire email and that was exactly what I did. While doing that I discovered something shocking and that is the reason I thought to write this article and I hope that it benefits and charges you to change your habit towards your email.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I discovered
&lt;/h3&gt;

&lt;p&gt;As I was taking my time to properly sort my mail moving from tab to tab (by the way I use Gmail) I finally clicked on &lt;strong&gt;“All Mail”&lt;/strong&gt; and was shocked to see tons of unread emails that never made it to my inbox and some even carried the inbox flag. So I continued the email sanitation by deleting irrelevant emails and clicking the unsubscribe buttons whenever necessary.&lt;br&gt;
Just as I was doing this, I came across two mails that didn't look like marketing or spam so I decided to take a peek into its content and alas! my suspicion was true in the two instances.&lt;/p&gt;

&lt;p&gt;The two mails were interview invitations from two organizations, one local, the other foreign. I was dumbfounded for a little while because the emails have been sitting somewhere in my mail for over four (4) months and that was the first time I was seeing it.&lt;br&gt;
On looking closely at the timeframe of the emails, it was around the same time I was out of a job and was looking for new opportunities. During that time I had sent out multiple applications and reached out to my network for a new job.&lt;/p&gt;

&lt;p&gt;Eventually, when I did some research about the two organizations, I discovered that I never directly applied to them which means someone had dropped my contact as a form of referral at the companies and you know what they say about referrals when it comes to job search 😭.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Yes, just like that, it dawned on me that I had missed what could have turned out to be an interesting opportunity had all mails carrying the inbox flag actually did make it to my inbox or had I made a habit of always checking all emails instead of just the ones that make it to my inbox and spam&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y9382wcY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p2shg029hzz7m7ajo2mj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y9382wcY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p2shg029hzz7m7ajo2mj.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://bufordcoc.com/sermons/missed-opportunities/"&gt;image source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I say your email could be your biggest career advancement enemy?
&lt;/h2&gt;

&lt;p&gt;Come to think of it, email is the professional means of communicating official information between different parties. What this means is that if you’re going to get a new job or contract you will most likely get to know via an email, likewise, if you’re being promoted or probably getting a raise it will definitely be accompanied by an email, the same is true even for business owners/entrepreneurs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Moreover, With different anti-spam algorithms flying around chances are that some of your important emails may be wrongly classified and never make it to your inbox. If you are like me who prioritizes my inbox and rarely check spam or other tabs quickly enough, you might miss out on great opportunities&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, there are other times when our emails aren’t wrongly classified but we are just too lazy to read and properly sort our mails and by that, we have so many unread emails at the same time making it very easy for important ones to get lost in the stack of read/unread emails. In this case, it is not the email service providers that are hampering your professional progress. It is you due to your bad habit towards your email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EWyMrXoj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vshpm5r3a4et20w3vdzv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EWyMrXoj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vshpm5r3a4et20w3vdzv.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.neilmd.com/rocky-balboa-on-taking-responsibility-for-your-life/"&gt;Image source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I know some might be thinking, “of course, I’ll pay better attention when applying for a new job or when I have something important on the way”, this can not be more wrong. There are times when you might have been referred or otherwise and a great opportunity would just be missed because you are never in the habit of tidying your email until you have something on the way.&lt;br&gt;
This is even more terrible because your bad email habit coupled with some wrong email classifications is a recipe for professional disaster.&lt;/p&gt;

&lt;p&gt;I did a poll on Twitter barely 24 hours to publishing this article regarding how people miss opportunities because they got to see email a little too late and the result I got was alarming. From the result, 65.4 % of the respondents said they have missed opportunities due to seeing email a little too late. That’s some very scary percentage. Here is the link to the poll &lt;a href="https://twitter.com/iMichaelOwolabi/status/1277699498190483457?s=20"&gt;https://twitter.com/iMichaelOwolabi/status/1277699498190483457?s=20&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--logjtbCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jxil7jrmh4ay2mnro2zt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--logjtbCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jxil7jrmh4ay2mnro2zt.png" alt="Twitter poll showing the result of a question on email issues"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How can this be resolved 🤔?
&lt;/h3&gt;

&lt;p&gt;Now that we have identified some of the reasons that may be contributing to missing great opportunities emanating from our emails and its usage, below are the mitigating steps that can be taken to ensure we don’t miss great opportunities to poor email management.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Check all emails, not just the ones in your inbox
&lt;/h3&gt;

&lt;p&gt;Just like I stated earlier that as a Gmail user, even some emails with the inbox flag did not appear in my inbox and I did not get to see them until I checked the All mail section so also can your important emails be wrongly classified and placed under a different tab than your inbox so, always ensure that you check all emails from all tabs so as to ensure that you do not miss a great opportunity due to wrong email classification.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Read your emails daily
&lt;/h3&gt;

&lt;p&gt;There’s no fun in having tons of unread emails and increasing the chance of missing important ones. Make a habit of actually reading your emails daily. Not just logging into your email system and scanning through, but properly reading them and deleting unnecessary ones so that it becomes easier for you to spot new emails one of which may come bearing good news of juicy opportunities.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Unsubscribe often
&lt;/h3&gt;

&lt;p&gt;Yes, I said it. Most of the emails we get are usually some marketing related stuff that does not directly have anything to do with us or help our career in the shortest time possible. Be truthful to yourself while wielding the “axe of unsubscribe” and properly weed out all mail correspondence that is not beneficial to you in any way. Also, swiftly click the unsubscribe button because if you don’t, these are the ones that will mask important emails thereby increasing your chance of missing out on what could be a life-changing opportunity.&lt;/p&gt;

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

&lt;p&gt;Emails will continue to be an important part of our professional lives and we must be deliberate about using it well to our advantage. Failure to do this may gravely impact our careers and what should have been a great tool for us could easily turn out to be our biggest career advancement enemy.&lt;br&gt;
So:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Check all emails not just the ones in your inbox&lt;/li&gt;
&lt;li&gt;Read your emails daily&lt;/li&gt;
&lt;li&gt;Unsubscribe often&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have other great tips, feel free to share it in the comment section. I can also be reached on twitter via &lt;a href="https://twitter.com/iMichaelOwolabi"&gt;@iMichaelOwolabi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>email</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Why you should learn Git 📌</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Fri, 05 Jun 2020 17:18:44 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/why-you-should-learn-git-16el</link>
      <guid>https://dev.to/imichaelowolabi/why-you-should-learn-git-16el</guid>
      <description>&lt;p&gt;This article is about why I think everyone (Software Developers) should learn Git but before we delve into this proper, I want us to explore briefly what Git is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fun Fact 😊
&lt;/h3&gt;

&lt;p&gt;Git was developed in 2005 by Linus Torvalds majorly for the development of the Linux kernel after a fallout between the Linus team and the Bitkeeper proprietary DVCS solution provider. More about that &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-A-Short-History-of-Git" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Git❓
&lt;/h3&gt;

&lt;p&gt;Git is an open-source distributed version control system used for tracking changes in source code during software development. It is designed for coordinating work among programmers, but it can be used to track changes in any set of files. Its goals include speed, data integrity, and support for distributed, non-linear workflows. &lt;a href="https://en.wikipedia.org/wiki/Git" rel="noopener noreferrer"&gt;wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you examine the definition above well, you’ll notice that Git is all about collaboration (coordinating work among programmers), integrity (tracking changes), etc. In Git, if it’s ever commited it will be tracked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "If it’s ever comitted it will be tracked"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F115r6qp4qr1azdmhk7t9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F115r6qp4qr1azdmhk7t9.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giphy.com/gifs/art-video-design-3o7bub7jw4P5FS65l6" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have refreshed our memory of what Git is, let us talk about why you should learn it ASAP.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Git❓
&lt;/h3&gt;

&lt;p&gt;As software developers, whether you are hoping to build the next thing that will change the course of history or you just want to know enough to make ends meet, chances are you will not do this alone which means you need others to actualize that dream. If you fall anywhere within this wide spectrum then you need to learn git as soon as possible.&lt;/p&gt;
&lt;h4&gt;
  
  
  Git is the most popular distributed version control system
&lt;/h4&gt;

&lt;p&gt;Since my career in software development, I have never seen a job requirement that required any other form of &lt;strong&gt;DVCS&lt;/strong&gt; than Git. As a matter of fact, more often than not you will not see Git as a requirement for most job descriptions because it is mostly assumed that as a Software Developer, you should already know and be using Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Git is the most popular DVCS"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  You will work with others 👥
&lt;/h4&gt;

&lt;p&gt;Another reason you should learn git and learn it now is that you will most likely have to work with others either as part of a team in your job or just to collaborate with others in developing various software products. When it comes to collaborating among software development teams in tracking source code changes, nothing does it better and as smoothly as Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"...nothing does it better and as smoothly as Git."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Git is not as hard as you think 💪🏾
&lt;/h4&gt;

&lt;p&gt;For many people, the reason they defer learning Git until much later is because of the impression that Git is a hard concept and that they need to memorize a whole bunch of various git commands to get going. This is not true❗️&lt;br&gt;
The Git commands you will most frequently use are just very few and once you start using them, you’ll see that it’s just a breeze 👌🏾.&lt;/p&gt;

&lt;h4&gt;
  
  
  Remote is becoming the norm 👩🏽‍💻
&lt;/h4&gt;

&lt;p&gt;Gone are the days when software development teams are constrained by physical proximity when all the members must be co-located in the same location to get work done. Remote work has been around for a while but it is getting more and more popular by the day. The current reality of the Covid-19 Pandemic has also massively accelerated the adoption of the remote culture and if you’re going to thrive as a software developer working remotely, you need to have a good command of basic Git.&lt;/p&gt;

&lt;p&gt;The above are a few of the reasons you should learn Git and learn it NOW.&lt;/p&gt;

&lt;p&gt;Want to begin your Git adventure already? below are some great resources that can help you quickly get started:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners" rel="noopener noreferrer"&gt;https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F" rel="noopener noreferrer"&gt;https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://try.github.io/" rel="noopener noreferrer"&gt;https://try.github.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/what-is-git-and-how-to-use-it-c341b049ae61/" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/news/what-is-git-and-how-to-use-it-c341b049ae61/&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PL4cUxeGkcC9goXbgTDQ0n_4TBzOO0ocPR" rel="noopener noreferrer"&gt;https://www.youtube.com/playlist?list=PL4cUxeGkcC9goXbgTDQ0n_4TBzOO0ocPR&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also follow &lt;a class="mentioned-user" href="https://dev.to/unseenwizzard"&gt;@unseenwizzard&lt;/a&gt; here on DEV, he's a git guru and has some nice contents on the subject&lt;/p&gt;

&lt;p&gt;Let me know what you think in the comment section. If you love this article don't forget to drop a ❤️ and share it within your network. I can also be reached on Twitter via &lt;a href="https://twitter.com/iMichaelOwolabi" rel="noopener noreferrer"&gt;@iMichaelOwolabi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>codenewbie</category>
      <category>career</category>
      <category>github</category>
    </item>
    <item>
      <title>How to Implement Login with Google in Nest JS</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Thu, 30 Apr 2020 17:18:55 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/how-to-implement-login-with-google-in-nest-js-2aoa</link>
      <guid>https://dev.to/imichaelowolabi/how-to-implement-login-with-google-in-nest-js-2aoa</guid>
      <description>&lt;p&gt;In this article, we are going to implement (OAuth) login with google in Nest JS. Coming from Express, implementing OAuth in Nest JS may seem not so straight forward especially when using the general passport module because, in Nest JS, so many things have been implemented and wrapped in various nest modules that can be used out of the box by developers building in this awesome framework. While this is is a very good thing, you have to take the time to figure out how some of the regular things work differently in Nest.&lt;/p&gt;

&lt;p&gt;Nest JS uses Typescript but allows the use of vanilla JS so it does not really force developers to write in typescript.&lt;/p&gt;

&lt;p&gt;Nest is built on the popular Express framework and some of the concepts are very familiar but if you have never worked with Nest and want to get more from this article then I suggest that you take a few minutes to familiarize yourself with the framework &lt;a href="https://docs.nestjs.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, the overview section will definitely get you going quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;To follow through this tutorial you must have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node JS&lt;/li&gt;
&lt;li&gt;NPM&lt;/li&gt;
&lt;li&gt;Web Browser&lt;/li&gt;
&lt;li&gt;Code Editor (VsCode)&lt;/li&gt;
&lt;li&gt;Gmail Account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don’t have Node.js installed just head on to the official &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; website to get a copy of Node.js for your platform. Once you install Node.js you will automatically have npm installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;To get started, we are going to scaffold a new nest project using the nest cli so we’ll install it globally by running the following command on the terminal:&lt;/p&gt;

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

npm i -g @nestjs/cli


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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Creating a new Nest project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since we have just installed nest cli globally, we can use it to setup a new Nest project server by running the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd desktop &amp;amp;&amp;amp; nest new google-login &amp;amp;&amp;amp; cd google-login


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

&lt;/div&gt;
&lt;p&gt;Open the generated project folder in your editor of choice which should look like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flx585dgn6k25xhc8gui4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flx585dgn6k25xhc8gui4.png" alt="Alt Text" width="580" height="804"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For this project we will be using passport, dotenv to manage our environment variables, so let’s install them by running the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install --save @nestjs/passport passport passport-google-oauth20 dotenv
npm install -D @types/passport-google-oauth20


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

&lt;/div&gt;
&lt;p&gt;Test the server by running: ```npm&lt;br&gt;
&lt;br&gt;
 run start:dev&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now open up your browser and type the localhost URL on which Nest is running **‘localhost:3000/’** you should get **Hello world** just as shown below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/an1wvy071ct9rgbscgi3.png)

Now we are good to go 🚀

### Create the Google Application

To use google OAuth we have to create an application on google developer console hence the need for the Gmail account. Visit [https://console.developers.google.com/](https://console.developers.google.com/) and create an application which we will use to set up the authentication in Nest JS. So when you visit the google developer console URL you should see something similar to the screen below

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gfwevy9t1tmjuzug40gw.png)


Click on **“NEW PROJECT”** and fill in your desired name and then click the Create button.

**Set Project Consent Screen**

The project consent screen is what is displayed to the user whenever they want to use our google application to login to our system. To set the consent screen 
click “OAuth consent screen” menu at the sidebar

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yoi62c37kbw01gnx2mmf.png)

Select External so the application can be used by any google account and then click **CREATE**.

On the consent screen, make sure you only fill the “Application Name” and nothing else since this is just for testing purposes. If we are creating a live application then other fields can be filled which will then need to go through the approval process. Click save when you are done.

**Get App credentials**

To get our app credentials which will be used to authenticate the app with google API click on “Credentials” menu at the sidebar.
* Click Create credentials and select OAuth Client ID
* Select Web applications on the next screen then fill the Authorized JavaScript origins and the redirect URI.

The Authorized JavaScript origins refers to where our request will be coming from which in this case is localhost, so enter **http://localhost:3000** and for the Authorized redirect URIs enter **http://localhost:3000/google/redirect**.

Kindly note that the redirect URI simply refers to the particular endpoint in our app where google will return the response after authenticating a user.
Click save when you’re done. You should get your app credentials from the screen below

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wsndg61fgc97gmq2ltvx.png)

Copy the credentials and save it somewhere because we are going to use it in our app.

### Setup Google Login (OAuth)
The first thing to do is to setup the google strategy which is the core of our google login implementation. Create a file named google.strategy.ts in the src folder and add the following code into the file.

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;In the code above, we loaded in all needed dependencies and then created a &lt;strong&gt;GoogleStrategy&lt;/strong&gt; class as a sub-class of the &lt;strong&gt;PassportStrategy&lt;/strong&gt; class. Every individual class that we define which uses passport must extend the PassportStrategy class which is a dedicated module from the &lt;strong&gt;‘@nestjs/passport’&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We then pass in all the required parameters for the google strategy.&lt;br&gt;
&lt;strong&gt;CLIENT_ID&lt;/strong&gt; and &lt;strong&gt;CLIENT SECRET&lt;/strong&gt; are the application ID and SECRET we got from google when we created the application which was loaded in through the environment variable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CallbackURL&lt;/strong&gt; is the particular endpoint in our app which google will return control to after authenticating a user. Remember we defined this also on google while creating our application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope&lt;/strong&gt; refers to the set of user information that we require from google needed in our app. In this case, basic user information captured in the profile and the user email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The validate method&lt;/strong&gt; refers to the verify callback function that will be executed after google returns to us the requested user information. This is where we decide what we want to do with the user information, in this case, we are just extracting and formatting the information we need from the returned user profile and adding it to the user object which will be available on the global request object. This is done by calling done and passing into it null (which means no error) and the user object.&lt;/p&gt;

&lt;p&gt;Don’t forget to add the environment variables just as shown below in a &lt;strong&gt;.env&lt;/strong&gt; file at the root of the project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcb4eniyzf6w3akkdfmr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcb4eniyzf6w3akkdfmr0.png" alt="Alt Text" width="510" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
We could easily do all we want to do with the user information in the strategy file but Nest JS is very big on Single Responsibility Principle and since ordinarily in a live application, we will most likely want to save the user information in the database, such kind of actions is dedicated to something called services in Nest JS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup the Controller, Route, and Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For us to be able to login with google, we must setup the appropriate endpoint in our application and this is the job of controllers in Nest JS. To do this, open up the app.controller.ts file in the src folder and replace the content with the following code.&lt;/p&gt;

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;In Nest JS, routes can be setup at the controller level and/or at the request method level so in the code above we setup the google login route at the controller decorator level which means that every request in the controller will go through the google endpoint. You can read more on routing in Nest JS &lt;a href="https://docs.nestjs.com/controllers#routing" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first Get request is the endpoint that activates the google authentication through a special Guard from the “@nestjs/passport” module placed on the endpoint called &lt;strong&gt;“AuthGaurd”&lt;/strong&gt;. We pass in ‘google’ as the argument to this AuthGuard to signify that we want to use the google strategy from the passport module to authenticate the request on this endpoint.&lt;/p&gt;

&lt;p&gt;The second Get request refers to the second endpoint where google will redirect to (redirec URL) after authenticating a user. This endpoint also uses the special AuthGuard. After the done function in the validate method from the google strategy file is called, control is returned back to the googleLogin function on this controller. Let’s create the googleLogin function.&lt;/p&gt;

&lt;p&gt;Open the app.service.ts file in the src folder and add the following code&lt;/p&gt;

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;Here we are just returning back the user information from google which was added to the request object from the validate method in the google strategy file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bringing it all together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As of now, our application still doesn’t know of the google strategy that was setup, so we need to make it available in the app module before we can use it.&lt;br&gt;
Open the app.module.ts file and add the google strategy as a service in the provider array. Your app module file should look like the one below&lt;/p&gt;

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;h3&gt;
  
  
  Testing Our App
&lt;/h3&gt;

&lt;p&gt;Start the app by running ```npm&lt;/p&gt;

&lt;p&gt;run start:dev&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Launch any browser on your computer and visit the google endpoint at &lt;strong&gt;localhost:3000/google&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should see something similar to the screen below&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbon24xgtop4zwur7825.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcbon24xgtop4zwur7825.png" alt="Alt Text" width="800" height="695"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;User information from google after login is shown below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3009xu16qxc9qcfkoklz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3009xu16qxc9qcfkoklz.png" alt="Alt Text" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; You have just successfully implemented Google OAuth (Login with Google) in a Nest JS application.&lt;/p&gt;

&lt;p&gt;Completed code can be found here: &lt;a href="https://github.com/iMichaelOwolabi/google-oauth-nestjs" rel="noopener noreferrer"&gt;https://github.com/iMichaelOwolabi/google-oauth-nestjs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can drop your comments here if you have one and for further engagements, I can always be reached on Twitter &lt;a href="https://twitter.com/iMichaelOwolabi" rel="noopener noreferrer"&gt;@iMichaelOwolabi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>nestjs</category>
      <category>google</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to know You're ready for a Software Developer job as a Beginner</title>
      <dc:creator>Michael Owolabi</dc:creator>
      <pubDate>Sat, 18 Apr 2020 16:58:39 +0000</pubDate>
      <link>https://dev.to/imichaelowolabi/how-to-know-you-re-ready-for-a-software-developer-job-as-a-beginner-2o7k</link>
      <guid>https://dev.to/imichaelowolabi/how-to-know-you-re-ready-for-a-software-developer-job-as-a-beginner-2o7k</guid>
      <description>&lt;p&gt;So you’ve been learning to code for a few months, finished from a Bootcamp or just fresh out of grad school and you’re wondering if you should send out that application because you’re not sure if you’re ready. This is the dilemma many of us find ourselves when trying to get our first software developer job. This can even be the case when trying to change jobs or applying for a more senior position than our current level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcyrvysn91jx9hf0e03ik.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcyrvysn91jx9hf0e03ik.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is especially a tough case for those who are self-taught without any form of degrees or boot-camp experience, there is always the extra worry of not having a degree, but hey, this is not medicine where you need a license to practice. I know you must have heard this before but let me re-emphasize it that you can get a great software development job without any form of degree.&lt;/p&gt;

&lt;p&gt;Taking that out of the way, so how do you know if you’re ready for a job as a beginner? Well, I’m happy to announce to you that you will never truly know until you send out that application, get that interview, get rejected, learn from rejections, repeat until you get a befitting organization lucky to have such a great person as yourself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgi1azcgsk07vbuqmqvpj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgi1azcgsk07vbuqmqvpj.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anything else you get from this article that doesn’t end with you taking that leap of faith and sending out that application is a total waste of time. This is very important because you can spend years on tutorials and documentation, and not feel ready.&lt;/p&gt;

&lt;p&gt;So then, let us look at some ways to brace up and boost our morale leading to sending out a great application for that job you think you aren’t ready for.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find a Support System.
&lt;/h3&gt;

&lt;p&gt;If you can self motivate all of the time that’s fantastic. But since most of us can use a little “pat on the back” alongside some nudge every now and then, it is very important that you find a support system. This could be a friend, colleague, mentor, community, anyone or anything you can draw strength from which can help get you going even when all looks bleak. &lt;/p&gt;

&lt;p&gt;This is very important because victory only lies in not giving up and to not give up in spite of challenges requires motivation, getting motivated is where the support system plays a role. I know this seems obvious but you need to ensure that whatever support system you get is &lt;strong&gt;one that lifts you up and not one that puts you down.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fle3vikre68iw2ai646yw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fle3vikre68iw2ai646yw.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Learn more | Code more | Build more
&lt;/h3&gt;

&lt;p&gt;Having completed a boot-camp, graduated, or completed some form of personal learning. This is not the time to relax and go on a coding sabbatical while hoping to secure your first software development job. In contrast, this is the time to continue to solidify your knowledge through continuous learning, coding, and building as much as you can. &lt;/p&gt;

&lt;p&gt;I can’t think of a more confidence booster than getting your hands dirty in code. The more you learn, code, and build, the more confident and ready you are for that job as a software developer.&lt;/p&gt;

&lt;p&gt;Danny Thompson &lt;a class="mentioned-user" href="https://dev.to/dthompsondev"&gt;@dthompsondev&lt;/a&gt; put it so well in a 39 seconds video posted on his twitter page. Kindly take out time to watch the video &lt;a href="https://twitter.com/DThompsonDev/status/1248605648587304961?s=20" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp6k08p44pmv7gd589mxl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fp6k08p44pmv7gd589mxl.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Invest in Soft Skills
&lt;/h3&gt;

&lt;p&gt;You’ve studied and are very confident in your skills, you just graduated with spectacular grades or maybe you’ve just finished from a very intense boot-camp and you’re literally beaming code. That's great, but how are you going to convince the hiring manager you’ve got what it takes if you cannot communicate it properly?&lt;/p&gt;

&lt;p&gt;As software developers, we are first humans and are not separated from the rest of the world so we have to know how to relate with others, communicate properly, listen and not just hear stuff. So as you’re are building your technical muscles you should also find time to build various soft skills that will not only ensure that you secure that job, but also help you retain it. &lt;/p&gt;

&lt;p&gt;Your exceptional soft skills may be the differentiating factor between you and the next great software developer who also applied for that job so find the time to work on your soft skills.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remember
&lt;/h3&gt;

&lt;p&gt;You can prepare for several months or even years and still not feel ready for a software development job because there will always be something that you don’t know. So as a beginner who has put in the time to learn either as self-taught, from boot-camp, or a graduate. The key is in sending out the application regardless of how unsure you think you are.&lt;br&gt;
Find you a support system that motivates rather than de-motivate you, learn more | code more | build more, and invest in soft skills.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You definitely will never know if you’re ready or not until you send that application, get that interview and finally get that job.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb5ot5tzwxmpuf3xnzxbt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb5ot5tzwxmpuf3xnzxbt.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image Sources:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.technojobs.co.uk/info/developer-guides/software-developer-job-description-template.phtml" rel="noopener noreferrer"&gt;https://www.technojobs.co.uk/info/developer-guides/software-developer-job-description-template.phtml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://giphy.com/" rel="noopener noreferrer"&gt;https://giphy.com/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>codenewbie</category>
      <category>career</category>
      <category>beginners</category>
      <category>software</category>
    </item>
  </channel>
</rss>
