<?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: Moshfiqur Rahman</title>
    <description>The latest articles on DEV Community by Moshfiqur Rahman (@moshfiqurrahman).</description>
    <link>https://dev.to/moshfiqurrahman</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4183918%2Fbc4d3ddc-e527-4c92-af87-4e0788538285.png</url>
      <title>DEV Community: Moshfiqur Rahman</title>
      <link>https://dev.to/moshfiqurrahman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moshfiqurrahman"/>
    <language>en</language>
    <item>
      <title>MongoDB Indexing Explained: Make Your Queries 100x Faster</title>
      <dc:creator>Moshfiqur Rahman</dc:creator>
      <pubDate>Mon, 02 Nov 2026 09:32:40 +0000</pubDate>
      <link>https://dev.to/moshfiqurrahman/mongodb-indexing-explained-make-your-queries-100x-faster-3cm1</link>
      <guid>https://dev.to/moshfiqurrahman/mongodb-indexing-explained-make-your-queries-100x-faster-3cm1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Imagine your application has only 50 users during development. Everything works fine, and your database queries are fast.&lt;/p&gt;

&lt;p&gt;A few months later, your application grows. Now, your users collection contains one million documents.&lt;/p&gt;

&lt;p&gt;Suddenly, a simple login query starts taking several seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rahim@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query looks simple, but MongoDB may need to check every document in the collection to find the matching email.&lt;/p&gt;

&lt;p&gt;This is where indexing helps.&lt;/p&gt;

&lt;p&gt;You can create an index on the email field with just one line:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now MongoDB can find the matching document without checking the entire collection.&lt;/p&gt;

&lt;p&gt;In this article, we will look at how MongoDB indexes work, the different types of indexes, how to create compound indexes, and how to check whether an index is helping your queries.&lt;/p&gt;

&lt;p&gt;All examples use &lt;code&gt;mongosh&lt;/code&gt; with simple users and orders collections.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a MongoDB Index?
&lt;/h2&gt;

&lt;p&gt;Think about the index at the back of a textbook.&lt;/p&gt;

&lt;p&gt;If you want to find a specific topic, you do not need to read every page. You check the index, find the page number, and go directly to that page.&lt;/p&gt;

&lt;p&gt;MongoDB indexes work in a similar way.&lt;/p&gt;

&lt;p&gt;An index is a data structure that stores field values in an organized order. MongoDB uses it to find documents without scanning the entire collection.&lt;/p&gt;

&lt;p&gt;MongoDB uses B-tree indexes for most standard index types.&lt;/p&gt;

&lt;p&gt;For example, if you frequently search users by email, you can create an index like this:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;One thing to remember: every MongoDB collection already has an index on the &lt;code&gt;_id&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;You do not need to create that index yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  COLLSCAN vs IXSCAN
&lt;/h2&gt;

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

&lt;p&gt;When MongoDB runs a query, it chooses a plan to find the matching documents.&lt;/p&gt;

&lt;p&gt;Two stages are worth understanding:&lt;/p&gt;

&lt;p&gt;COLLSCAN (Collection Scan)&lt;/p&gt;

&lt;p&gt;MongoDB checks documents one by one until it finds the matching results.&lt;/p&gt;

&lt;p&gt;This can become slow when a collection contains a large amount of data.&lt;/p&gt;

&lt;p&gt;IXSCAN (Index Scan)&lt;/p&gt;

&lt;p&gt;MongoDB searches through an index to find matching documents. It usually needs to examine far fewer documents.&lt;/p&gt;

&lt;p&gt;You can check which approach MongoDB uses with &lt;code&gt;explain()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rahim@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executionStats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before creating an index, the output might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queryPlanner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"winningPlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COLLSCAN"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"executionStats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nReturned"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"totalDocsExamined"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"executionTimeMillis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating the index, you might see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queryPlanner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"winningPlan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FETCH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"inputStage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IXSCAN"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"executionStats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nReturned"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"totalDocsExamined"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"executionTimeMillis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the difference.&lt;/p&gt;

&lt;p&gt;Before indexing, MongoDB examined one million documents. After indexing, it examined only one.&lt;/p&gt;

&lt;p&gt;These numbers are examples. Actual results depend on your data, hardware, and query.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Your First Index
&lt;/h2&gt;

&lt;p&gt;Creating an index in MongoDB is straightforward.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;createIndex()&lt;/code&gt; and provide the field name with its direction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; means ascending order.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-1&lt;/code&gt; means descending order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create an index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Check existing indexes&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getIndexes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Remove an index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dropIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email_1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MongoDB creates an index name automatically based on the field and direction.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;email:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates an index named:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;For a single-field index, MongoDB can scan in either direction, so the direction usually does not make much difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of MongoDB Indexes
&lt;/h2&gt;

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

&lt;p&gt;MongoDB supports several types of indexes. Each one is useful for a different kind of query.&lt;/p&gt;

&lt;p&gt;Let's go through the ones you should know.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Single Field Index
&lt;/h3&gt;

&lt;p&gt;A single-field index is created on one field.&lt;/p&gt;

&lt;p&gt;It is useful when your application frequently searches or sorts documents using that field.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Now MongoDB can use this index for queries that search or sort by &lt;code&gt;price&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Compound Index
&lt;/h3&gt;

&lt;p&gt;A compound index contains multiple fields.&lt;/p&gt;

&lt;p&gt;You will often use this type of index in real applications because queries usually depend on more than one field.&lt;/p&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This index can help queries that filter by &lt;code&gt;customerId&lt;/code&gt; and sort by &lt;code&gt;createdAt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The order of fields matters.&lt;/p&gt;

&lt;p&gt;Compound indexes also follow something called the prefix rule.&lt;/p&gt;

&lt;p&gt;For example, consider this index:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;MongoDB can use this index for queries involving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;age&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it generally cannot use this index efficiently for a query that searches only by &lt;code&gt;email&lt;/code&gt; or only by &lt;code&gt;age&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Keep this in mind when designing compound indexes.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Multikey Index
&lt;/h3&gt;

&lt;p&gt;A multikey index is used when a field contains an array.&lt;/p&gt;

&lt;p&gt;MongoDB automatically creates index entries for the array elements.&lt;/p&gt;

&lt;p&gt;You do not need to configure anything special.&lt;/p&gt;

&lt;p&gt;For example, imagine a document like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;title:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MongoDB 101"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;tags:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nosql"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"beginner"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create an index on the &lt;code&gt;tags&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you can search for posts using an array element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nosql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important limitation: a compound multikey index can have at most one indexed array field in each document.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Text Index
&lt;/h3&gt;

&lt;p&gt;A text index allows you to search string content in a collection.&lt;/p&gt;

&lt;p&gt;It is useful for basic text searches.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can search for words in those fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$search&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;indexing tutorial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A collection can have only one text index, although that index can cover multiple fields.&lt;/p&gt;

&lt;p&gt;For more advanced search features, such as typo tolerance and relevance tuning, you can look into MongoDB Atlas Search.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Unique Index
&lt;/h3&gt;

&lt;p&gt;A unique index prevents duplicate values in a field.&lt;/p&gt;

&lt;p&gt;It is useful for fields like email addresses, usernames, and other values that must be unique.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now MongoDB will not allow two documents to have the same email value.&lt;/p&gt;

&lt;p&gt;This helps maintain data consistency at the database level.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. TTL Index
&lt;/h3&gt;

&lt;p&gt;A TTL (Time To Live) index automatically removes documents after a specified amount of time.&lt;/p&gt;

&lt;p&gt;It is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User sessions&lt;/li&gt;
&lt;li&gt;OTP records&lt;/li&gt;
&lt;li&gt;Temporary data&lt;/li&gt;
&lt;li&gt;Short-lived logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you can automatically delete session documents one hour after their creation time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expireAfterSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The indexed field must contain a date value.&lt;/p&gt;

&lt;p&gt;One thing to remember: MongoDB does not delete expired documents at the exact second. Its background cleanup process runs periodically, usually around once a minute.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Partial Index
&lt;/h3&gt;

&lt;p&gt;A partial index stores entries only for documents that match a specific condition.&lt;/p&gt;

&lt;p&gt;This can reduce index size when you only need to query a certain group of documents.&lt;/p&gt;

&lt;p&gt;For example, suppose you frequently search for active users.&lt;/p&gt;

&lt;p&gt;Instead of indexing every user, you can create an index for active users only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lastLogin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;partialFilterExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MongoDB will include only documents where &lt;code&gt;status&lt;/code&gt; is &lt;code&gt;"active"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To use this index, your query must include a condition that matches the partial filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Sparse Index
&lt;/h3&gt;

&lt;p&gt;A sparse index skips documents that do not contain the indexed field.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sparse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Documents without a &lt;code&gt;phone&lt;/code&gt; field will not be included in this index.&lt;/p&gt;

&lt;p&gt;Partial indexes offer more control, but you may still find sparse indexes in existing projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Hashed Index
&lt;/h3&gt;

&lt;p&gt;A hashed index stores the hash of a field value instead of its original value.&lt;/p&gt;

&lt;p&gt;It supports equality queries, but not range queries.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hashed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hashed indexes are mainly useful in hashed sharding.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Geospatial Index
&lt;/h3&gt;

&lt;p&gt;Geospatial indexes help MongoDB work with location-based data.&lt;/p&gt;

&lt;p&gt;For example, you might need to find restaurants within 2 kilometers of a user's location.&lt;/p&gt;

&lt;p&gt;You can create a &lt;code&gt;2dsphere&lt;/code&gt; index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;places&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2dsphere&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then search for nearby places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;places&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$near&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$geometry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Point&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;90.4125&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;23.8103&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;$maxDistance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The coordinates are longitude and latitude, and the distance is measured in meters.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Wildcard Index
&lt;/h3&gt;

&lt;p&gt;Sometimes your documents contain dynamic fields, and you do not know in advance which fields users will search.&lt;/p&gt;

&lt;p&gt;A wildcard index can help with these situations.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;metadata.$**&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates an index for fields inside the &lt;code&gt;metadata&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;However, do not use wildcard indexes as a replacement for properly designed compound indexes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compound Indexes and the ESR Rule
&lt;/h2&gt;

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

&lt;p&gt;When creating compound indexes, the order of fields can have a big impact on query performance.&lt;/p&gt;

&lt;p&gt;A useful rule to follow is ESR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E: Equality&lt;/li&gt;
&lt;li&gt;S: Sort&lt;/li&gt;
&lt;li&gt;R: Range&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The general order is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Equality fields first.&lt;/li&gt;
&lt;li&gt;Sort fields next.&lt;/li&gt;
&lt;li&gt;Range fields last.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at an example.&lt;/p&gt;

&lt;p&gt;Suppose you have this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$gt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query does three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finds users with an active status.&lt;/li&gt;
&lt;li&gt;Sorts the results by creation date.&lt;/li&gt;
&lt;li&gt;Returns users older than 25.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following the ESR rule, you can create this index:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Why this order?&lt;/p&gt;

&lt;p&gt;First, MongoDB uses &lt;code&gt;status&lt;/code&gt; to narrow down the matching documents.&lt;/p&gt;

&lt;p&gt;Next, it can read the matching entries in &lt;code&gt;createdAt&lt;/code&gt; order from the index.&lt;/p&gt;

&lt;p&gt;Finally, it applies the range condition on &lt;code&gt;age&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This can help MongoDB avoid an additional in-memory sort.&lt;/p&gt;

&lt;p&gt;The ESR rule is a useful starting point, but the best index still depends on your query and data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Covered Queries
&lt;/h2&gt;

&lt;p&gt;A covered query is a query where all the fields needed for filtering and returning results are available in an index.&lt;/p&gt;

&lt;p&gt;This means MongoDB does not need to read the actual documents.&lt;/p&gt;

&lt;p&gt;Let's look at an example.&lt;/p&gt;

&lt;p&gt;First, create a compound index:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now run this query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rahim@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query uses &lt;code&gt;email&lt;/code&gt; for filtering and returns &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All these fields are available in the index.&lt;/p&gt;

&lt;p&gt;We also excluded &lt;code&gt;_id&lt;/code&gt; because MongoDB includes it by default, and it is not part of this index.&lt;/p&gt;

&lt;p&gt;You can check whether a query is covered using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executionStats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A covered query should show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalDocsExamined"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means MongoDB did not need to examine any documents to return the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Create an Index?
&lt;/h2&gt;

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

&lt;p&gt;Indexes can improve read performance, but they also have a cost.&lt;/p&gt;

&lt;p&gt;Every index takes up disk space and memory.&lt;/p&gt;

&lt;p&gt;MongoDB also needs to update indexes whenever documents are inserted, updated, or deleted.&lt;/p&gt;

&lt;p&gt;So creating too many indexes can slow down write operations.&lt;/p&gt;

&lt;p&gt;Here are some situations where an index is usually helpful.&lt;/p&gt;

&lt;p&gt;Create an index when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A field is frequently used in query filters.&lt;/li&gt;
&lt;li&gt;A field is commonly used in &lt;code&gt;sort()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A field is used as a join key in &lt;code&gt;$lookup&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A field has many different values, such as &lt;code&gt;email&lt;/code&gt; or &lt;code&gt;orderId&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be careful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The collection contains only a few hundred documents.&lt;/li&gt;
&lt;li&gt;Your application performs many writes but very few reads.&lt;/li&gt;
&lt;li&gt;You are indexing a field with only a few possible values, such as &lt;code&gt;isActive&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An existing compound index already covers the queries you need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, creating an index on a boolean field alone may not help much because there are only two possible values.&lt;/p&gt;

&lt;p&gt;The important thing is to create indexes based on the queries your application actually runs.&lt;/p&gt;

&lt;p&gt;Do not create an index on every field just because you can.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Read explain()
&lt;/h2&gt;

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

&lt;p&gt;When a query becomes slow, do not guess what is happening.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;explain("executionStats")&lt;/code&gt; to understand how MongoDB executes it.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;executionStats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three things you should check.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. winningPlan.stage
&lt;/h3&gt;

&lt;p&gt;Look at the winning execution plan.&lt;/p&gt;

&lt;p&gt;You will usually want to see &lt;code&gt;IXSCAN&lt;/code&gt; instead of &lt;code&gt;COLLSCAN&lt;/code&gt; for queries that benefit from an index.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;FETCH&lt;/code&gt; stage can also appear when MongoDB needs to read the matching documents after scanning the index.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. totalDocsExamined vs nReturned
&lt;/h3&gt;

&lt;p&gt;These two values help you understand how much work MongoDB is doing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;totalDocsExamined&lt;/code&gt; tells you how many documents MongoDB examined.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nReturned&lt;/code&gt; tells you how many documents the query returned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if MongoDB examines 100,000 documents but returns only 5, your query may need a better index.&lt;/p&gt;

&lt;p&gt;You should not expect these numbers to be identical for every query, but a large difference is worth investigating.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. executionTimeMillis
&lt;/h3&gt;

&lt;p&gt;This tells you how long the query took to execute.&lt;/p&gt;

&lt;p&gt;You can use it to compare query performance before and after creating an index.&lt;/p&gt;

&lt;p&gt;Also, look for a &lt;code&gt;SORT&lt;/code&gt; stage in the execution plan.&lt;/p&gt;

&lt;p&gt;It means MongoDB is performing an additional sort instead of reading the results in the required order from an index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing Indexes in Production
&lt;/h2&gt;

&lt;p&gt;Creating indexes is only part of the job.&lt;/p&gt;

&lt;p&gt;You should also check which indexes your application actually uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check Index Usage
&lt;/h3&gt;

&lt;p&gt;MongoDB provides &lt;code&gt;$indexStats&lt;/code&gt; to show how often indexes are used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$indexStats&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the &lt;code&gt;accesses.ops&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;It shows how many operations have used an index since the server was last started.&lt;/p&gt;

&lt;p&gt;If an index has not been used, it may be worth reviewing.&lt;/p&gt;

&lt;p&gt;However, do not remove an index based on usage statistics alone. Some indexes may only be needed for occasional reports or less frequent operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hide an Index Before Removing It
&lt;/h3&gt;

&lt;p&gt;If you are unsure whether an index is still needed, MongoDB allows you to hide it before deleting it.&lt;/p&gt;

&lt;p&gt;This feature is available in MongoDB 4.4 and later.&lt;/p&gt;

&lt;p&gt;A hidden index is still maintained by MongoDB, but the query planner will not use it.&lt;/p&gt;

&lt;p&gt;You can test your application without that index and bring it back if needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Hide an index&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hideIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customerId_1_createdAt_-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Make the index available again&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unhideIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;customerId_1_createdAt_-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is safer than immediately deleting an index from a production database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check Index Size
&lt;/h3&gt;

&lt;p&gt;You can also check how much space your indexes use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;totalIndexSize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;indexSizes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indexes that are frequently used should ideally fit in memory.&lt;/p&gt;

&lt;p&gt;If they do not, MongoDB may need to read index data from disk more often, which can affect query performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Indexes with Mongoose
&lt;/h2&gt;

&lt;p&gt;If you use Node.js and Mongoose, you can define indexes directly in your schemas.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can define a compound index like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;orderSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a unique email field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mongoose can build indexes automatically when your application starts.&lt;/p&gt;

&lt;p&gt;However, this may cause unnecessary load on a large production database.&lt;/p&gt;

&lt;p&gt;For production applications, many teams disable automatic index creation and manage indexes through database migrations or deployment scripts.&lt;/p&gt;

&lt;p&gt;You can disable automatic index creation like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;autoIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you more control over when and how indexes are created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Indexing Mistakes
&lt;/h2&gt;

&lt;p&gt;Here are some mistakes developers often make when working with MongoDB indexes.&lt;/p&gt;

&lt;p&gt;1. Creating an index on every field&lt;/p&gt;

&lt;p&gt;More indexes do not always mean better performance. They use additional storage and can slow down write operations.&lt;/p&gt;

&lt;p&gt;2. Using the wrong field order in compound indexes&lt;/p&gt;

&lt;p&gt;The order of fields matters. Keep the ESR rule in mind when designing compound indexes.&lt;/p&gt;

&lt;p&gt;3. Forgetting the prefix rule&lt;/p&gt;

&lt;p&gt;An index on &lt;code&gt;{ a: 1, b: 1 }&lt;/code&gt; is useful for queries on &lt;code&gt;a&lt;/code&gt; and on both &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;. It generally does not help a query that searches only by &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;4. Never checking explain()&lt;/p&gt;

&lt;p&gt;Do not assume MongoDB is using your index. Check the execution plan and measure the results.&lt;/p&gt;

&lt;p&gt;5. Keeping unused or duplicate indexes&lt;/p&gt;

&lt;p&gt;For example, an index on &lt;code&gt;{ a: 1 }&lt;/code&gt; may be unnecessary if an index on &lt;code&gt;{ a: 1, b: 1 }&lt;/code&gt; already covers the same queries.&lt;/p&gt;

&lt;p&gt;6. Expecting every regex query to use an index&lt;/p&gt;

&lt;p&gt;A case-sensitive regex such as &lt;code&gt;/^abc/&lt;/code&gt; can use an index efficiently.&lt;/p&gt;

&lt;p&gt;However, a regex like &lt;code&gt;/abc/&lt;/code&gt; generally cannot use an index in the same way.&lt;/p&gt;

&lt;p&gt;7. Creating indexes directly on a busy production database&lt;/p&gt;

&lt;p&gt;Always review the impact first. Test index changes in a staging environment before applying them to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  MongoDB Indexing Checklist
&lt;/h2&gt;

&lt;p&gt;Before considering your indexing work complete, go through this checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have I checked slow queries using &lt;code&gt;explain("executionStats")&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Is MongoDB using &lt;code&gt;IXSCAN&lt;/code&gt; where an index is useful?&lt;/li&gt;
&lt;li&gt;Does my compound index follow the ESR rule?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;totalDocsExamined&lt;/code&gt; reasonable compared to &lt;code&gt;nReturned&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Have I reviewed unused and duplicate indexes?&lt;/li&gt;
&lt;li&gt;Are my important indexes fitting in memory?&lt;/li&gt;
&lt;li&gt;Have I tested index changes before applying them to production?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;MongoDB indexing is an important part of working with databases, especially when your application starts handling more users and data.&lt;/p&gt;

&lt;p&gt;You do not need to memorize every index type from the beginning.&lt;/p&gt;

&lt;p&gt;Start with a few basic habits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check which queries are running slowly.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;explain("executionStats")&lt;/code&gt; to understand their execution plans.&lt;/li&gt;
&lt;li&gt;Create indexes based on your actual query patterns.&lt;/li&gt;
&lt;li&gt;Follow the ESR rule when creating compound indexes.&lt;/li&gt;
&lt;li&gt;Review your indexes from time to time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These habits will help you understand where your database is spending time and how to improve query performance.&lt;/p&gt;

&lt;p&gt;If you have worked with MongoDB indexing, I would like to hear about your experience.&lt;/p&gt;

&lt;p&gt;Have you ever fixed a slow query by creating the right index?&lt;/p&gt;

&lt;p&gt;Feel free to share your experience in the comments.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>database</category>
      <category>node</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Git Commit Messages Like a Pro: A Complete Guide to feat, fix, chore, init and More</title>
      <dc:creator>Moshfiqur Rahman</dc:creator>
      <pubDate>Mon, 02 Nov 2026 05:30:05 +0000</pubDate>
      <link>https://dev.to/moshfiqurrahman/git-commit-messages-like-a-pro-a-complete-guide-to-feat-fix-chore-init-and-more-98k</link>
      <guid>https://dev.to/moshfiqurrahman/git-commit-messages-like-a-pro-a-complete-guide-to-feat-fix-chore-init-and-more-98k</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Use &lt;code&gt;type(scope): subject&lt;/code&gt; to write clear commit messages. Choose the right type for each change, keep commits small, and commit when one task is complete. This makes your Git history easier to read and your work easier to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Git History Nobody Wants to Read
&lt;/h2&gt;

&lt;p&gt;A few months ago, I opened the Git history of an old project to find out when a bug was introduced.&lt;/p&gt;

&lt;p&gt;Here is what I found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final
final_v2
update
fixed stuff
asdf
final_final_REAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem? I could not understand what I had changed in any of those commits.&lt;/p&gt;

&lt;p&gt;I think many developers have done this at some point. I have done it too.&lt;/p&gt;

&lt;p&gt;When we are working on a project, writing &lt;code&gt;update&lt;/code&gt; or &lt;code&gt;fixed stuff&lt;/code&gt; may feel easy. But after a few months, those messages become useless.&lt;/p&gt;

&lt;p&gt;This is why writing good commit messages matters.&lt;/p&gt;

&lt;p&gt;A good commit message tells other developers what changed and why. It also helps you understand your own work when you return to a project later.&lt;/p&gt;

&lt;p&gt;Let's look at how to write better Git commit messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What Are Conventional Commits?
&lt;/h2&gt;

&lt;p&gt;Conventional Commits is a simple way to write Git commit messages using a common format.&lt;/p&gt;

&lt;p&gt;Instead of writing messages in different styles, we follow one structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;subject&amp;gt;

&amp;lt;body&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Here is a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(auth): add Google login"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand why this format is useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everyone can understand the commit history more easily.&lt;/li&gt;
&lt;li&gt;Developers can find changes faster.&lt;/li&gt;
&lt;li&gt;Code reviews become easier.&lt;/li&gt;
&lt;li&gt;Tools can create changelogs from commit messages.&lt;/li&gt;
&lt;li&gt;Release tools can use commit messages to decide version numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also makes teamwork easier because everyone follows the same format.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understanding the Commit Message Structure
&lt;/h2&gt;

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

&lt;p&gt;Let's break down this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): add Google login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three main parts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;feat&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It tells us what kind of change was made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope:&lt;/strong&gt; &lt;code&gt;auth&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It tells us which part of the project was changed. The scope is optional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject:&lt;/strong&gt; &lt;code&gt;add Google login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It gives a short description of the change.&lt;/p&gt;

&lt;p&gt;We can also add a body and footer when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Body&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The body explains why the change was made or gives more details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Footer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The footer can reference an issue or describe a breaking change.&lt;/p&gt;

&lt;p&gt;A complete example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): add Google login

Allow users to sign in using their Google accounts.
This makes the login process easier for new users.

Closes #42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need a body and footer for every commit. Use them when they add useful information.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Git Commit Types Explained
&lt;/h2&gt;

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

&lt;p&gt;This is one of the most important parts of writing good commit messages.&lt;/p&gt;

&lt;p&gt;Different types describe different kinds of changes.&lt;/p&gt;

&lt;p&gt;Let's go through the most commonly used types and see when to use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1. init
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;init&lt;/code&gt; when starting a new project or creating the initial project setup.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"init: set up Node.js project"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;init: create Next.js application
init: add initial project structure
init: configure TypeScript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use it when you are setting up a new project for the first time.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;init&lt;/code&gt; is a common team convention, not a required Conventional Commits type. You can also use &lt;code&gt;chore&lt;/code&gt; or another suitable type for initial setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2. feat
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;feat&lt;/code&gt; when adding a new feature to an application.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Google login.&lt;/li&gt;
&lt;li&gt;Creating a new API endpoint.&lt;/li&gt;
&lt;li&gt;Adding a search feature.&lt;/li&gt;
&lt;li&gt;Adding a new dashboard page.&lt;/li&gt;
&lt;li&gt;Adding payment integration.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(auth): add Google login"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(user): add profile update feature
feat(api): add product search endpoint
feat(payment): integrate Stripe checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;feat&lt;/code&gt; whenever you add new functionality that users or other parts of the application can use.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3. fix
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;fix&lt;/code&gt; when correcting a bug or something that does not work as expected.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login fails with valid credentials.&lt;/li&gt;
&lt;li&gt;Product quantity becomes negative.&lt;/li&gt;
&lt;li&gt;API returns incorrect data.&lt;/li&gt;
&lt;li&gt;Payment status is not updated.&lt;/li&gt;
&lt;li&gt;Form validation does not work correctly.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix(cart): prevent negative quantity"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(auth): handle expired access tokens
fix(api): return correct user data
fix(payment): prevent duplicate transactions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;fix&lt;/code&gt; when the main purpose of your change is to correct existing behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4. docs
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;docs&lt;/code&gt; when changing project documentation.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating README.&lt;/li&gt;
&lt;li&gt;Adding installation instructions.&lt;/li&gt;
&lt;li&gt;Writing API documentation.&lt;/li&gt;
&lt;li&gt;Updating project guides.&lt;/li&gt;
&lt;li&gt;Correcting documentation errors.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"docs(readme): add installation steps"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs(api): add authentication examples
docs(project): update setup guide
docs(readme): add environment variables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;docs&lt;/code&gt; when you are changing documentation rather than application functionality.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.5. style
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;style&lt;/code&gt; for code formatting changes that do not change how the application works.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixing indentation.&lt;/li&gt;
&lt;li&gt;Removing unnecessary spaces.&lt;/li&gt;
&lt;li&gt;Formatting code with Prettier.&lt;/li&gt;
&lt;li&gt;Changing semicolon usage.&lt;/li&gt;
&lt;li&gt;Organizing whitespace.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"style(ui): format components with prettier"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;style(api): fix code indentation
style(auth): apply consistent formatting
style(project): format TypeScript files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;style&lt;/code&gt; usually refers to code formatting, not visual changes to a website.&lt;/p&gt;

&lt;p&gt;If you change a button's color or add a new UI feature, use a suitable type such as &lt;code&gt;feat&lt;/code&gt; or &lt;code&gt;fix&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.6. refactor
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;refactor&lt;/code&gt; when improving the code structure without changing its existing behavior.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moving repeated logic into reusable functions.&lt;/li&gt;
&lt;li&gt;Separating business logic from controllers.&lt;/li&gt;
&lt;li&gt;Improving folder structure.&lt;/li&gt;
&lt;li&gt;Extracting validation middleware.&lt;/li&gt;
&lt;li&gt;Removing unnecessary code duplication.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"refactor(api): extract validation middleware"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;refactor(auth): simplify token validation
refactor(user): separate service logic
refactor(database): improve query structure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;refactor&lt;/code&gt; when the code structure changes but the application's external behavior remains the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.7. perf
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;perf&lt;/code&gt; when improving application performance.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimizing database queries.&lt;/li&gt;
&lt;li&gt;Reducing API response time.&lt;/li&gt;
&lt;li&gt;Adding database indexes.&lt;/li&gt;
&lt;li&gt;Improving caching.&lt;/li&gt;
&lt;li&gt;Reducing unnecessary API requests.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"perf(search): optimize database queries"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;perf(api): reduce response processing time
perf(database): add index for user queries
perf(cache): improve Redis caching
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;perf&lt;/code&gt; when your main goal is to make something faster or use fewer resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.8. test
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;test&lt;/code&gt; when adding, updating, or fixing tests.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding unit tests.&lt;/li&gt;
&lt;li&gt;Writing integration tests.&lt;/li&gt;
&lt;li&gt;Updating API test cases.&lt;/li&gt;
&lt;li&gt;Fixing failing test cases.&lt;/li&gt;
&lt;li&gt;Adding authentication tests.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test(auth): add login unit tests"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test(user): add profile update tests
test(api): cover error responses
test(payment): add checkout integration tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;test&lt;/code&gt; when the main change is related to tests rather than production code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.9. build
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;build&lt;/code&gt; when changing the build system, dependencies, or build configuration.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating package dependencies.&lt;/li&gt;
&lt;li&gt;Changing TypeScript configuration.&lt;/li&gt;
&lt;li&gt;Updating Docker build configuration.&lt;/li&gt;
&lt;li&gt;Changing Webpack or Vite settings.&lt;/li&gt;
&lt;li&gt;Updating build scripts.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"build(deps): update React dependencies"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build(docker): update Node.js image
build(config): update TypeScript settings
build(deps): add Zod dependency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.10. ci
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;ci&lt;/code&gt; when changing Continuous Integration or Continuous Delivery configuration.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding GitHub Actions.&lt;/li&gt;
&lt;li&gt;Updating automated test workflows.&lt;/li&gt;
&lt;li&gt;Changing deployment pipelines.&lt;/li&gt;
&lt;li&gt;Adding lint checks to CI.&lt;/li&gt;
&lt;li&gt;Updating build automation.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"ci(github): add test workflow"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ci(actions): run tests on pull requests
ci(deploy): update deployment workflow
ci(project): add lint checks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.11. chore
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;chore&lt;/code&gt; for general project maintenance that does not fit another suitable type.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cleaning unused configuration files.&lt;/li&gt;
&lt;li&gt;Organizing project scripts.&lt;/li&gt;
&lt;li&gt;Updating development tools.&lt;/li&gt;
&lt;li&gt;General maintenance tasks.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: update gitignore"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore(deps): update development dependencies
chore(project): remove unused files
chore(config): update environment example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One thing to remember:&lt;/strong&gt; Do not use &lt;code&gt;chore&lt;/code&gt; for every change.&lt;/p&gt;

&lt;p&gt;If you add a feature, use &lt;code&gt;feat&lt;/code&gt;. If you fix a bug, use &lt;code&gt;fix&lt;/code&gt;. If you improve the code structure, use &lt;code&gt;refactor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Choose the type that best describes the actual change.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.12. revert
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;revert&lt;/code&gt; when undoing a previous commit.&lt;/p&gt;

&lt;p&gt;For example, imagine you added a new feature but later found that it caused problems. You may need to revert that commit.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"revert: remove Google login feature"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also reference the original commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revert: remove Google login feature

This reverts commit abc1234.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When should you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;revert&lt;/code&gt; when you want to record the removal of an earlier change in Git history.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Other Commit Types You May See
&lt;/h2&gt;

&lt;p&gt;Apart from the common types above, you may see other commit types in different projects.&lt;/p&gt;

&lt;p&gt;These are not all part of the official Conventional Commits type list. Teams may define their own rules.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Common use&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Work in progress&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wip: work on user dashboard&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;merge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Merge-related commit&lt;/td&gt;
&lt;td&gt;&lt;code&gt;merge: integrate feature branch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;release&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Release preparation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;release: prepare version 1.2.0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;improvement&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;General improvement&lt;/td&gt;
&lt;td&gt;&lt;code&gt;improvement: improve search experience&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Initial project setup&lt;/td&gt;
&lt;td&gt;&lt;code&gt;init: create backend project&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use these only when your team has agreed to use them.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;wip&lt;/code&gt; may be useful on a personal development branch, but it is usually better to keep the main branch history clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. How to Choose the Right Scope
&lt;/h2&gt;

&lt;p&gt;A scope tells us which part of the project was changed.&lt;/p&gt;

&lt;p&gt;It makes commit messages easier to understand, especially in large applications.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(auth): add email verification"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix(payment): handle failed transactions"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"refactor(user): extract validation logic"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some common scopes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;auth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;User management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;payment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Payment features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API-related changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;database&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Database operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ui&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;User interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Admin dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;notification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;socket&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Real-time communication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You do not need to use every scope in every project.&lt;/p&gt;

&lt;p&gt;Choose scopes that match your project structure and keep them consistent across your team.&lt;/p&gt;

&lt;p&gt;Also, remember that the scope is optional.&lt;/p&gt;

&lt;p&gt;If a change does not belong to one clear area, you can leave it out.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. How to Write a Good Commit Subject
&lt;/h2&gt;

&lt;p&gt;The subject is the first line of your commit message.&lt;/p&gt;

&lt;p&gt;It should explain the change clearly and briefly.&lt;/p&gt;

&lt;p&gt;Here are five simple rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Use imperative wording&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;add user authentication
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;added user authentication
adding user authentication
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it as completing the sentence: "If applied, this commit will..."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Keep it short&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try to keep the subject around 50 characters when practical. This is a useful guideline, not a strict Git rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Avoid unnecessary punctuation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not add a full stop at the end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use clear words&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Avoid vague descriptions like &lt;code&gt;update code&lt;/code&gt; or &lt;code&gt;fix issue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Describe the actual change&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Write what changed, not a long explanation of how you implemented it.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. When Should You Add a Body or Footer?
&lt;/h2&gt;

&lt;p&gt;Most commits only need a subject line.&lt;/p&gt;

&lt;p&gt;But sometimes, the subject is not enough.&lt;/p&gt;

&lt;p&gt;That is when a body or footer becomes useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commit body
&lt;/h3&gt;

&lt;p&gt;Use the body to explain why you made the change or provide important details.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(auth): handle expired refresh tokens

Previously, expired refresh tokens were not handled
correctly. This change returns an authentication error
and asks the user to log in again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Commit footer
&lt;/h3&gt;

&lt;p&gt;Use the footer to reference an issue or describe a breaking change.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api): add product filtering

Allow users to filter products by category and price.

Closes #42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking changes
&lt;/h3&gt;

&lt;p&gt;A breaking change is a change that may cause existing users or applications to stop working without an update.&lt;/p&gt;

&lt;p&gt;You can mark it with &lt;code&gt;!&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api)!: change user response format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use a footer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api): change user response format

BREAKING CHANGE: The API now returns user data
inside a data object instead of returning an array.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both approaches are supported by Conventional Commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. When Should You Commit Your Code?
&lt;/h2&gt;

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

&lt;p&gt;This is an important question, especially for developers who are new to Git.&lt;/p&gt;

&lt;p&gt;My simple rule is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit when one logical piece of work is complete.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You do not need to wait until the entire feature or project is finished.&lt;/p&gt;

&lt;p&gt;You can commit after completing a small, meaningful task.&lt;/p&gt;

&lt;h3&gt;
  
  
  Good times to commit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. After completing a small feature&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, after implementing user registration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(auth): add user registration"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. After fixing a specific bug&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix(cart): update total after item removal"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. After completing a refactoring task&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"refactor(user): separate service logic"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. After adding or updating tests&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"test(auth): add registration tests"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Before switching to another task&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your current work is in a stable and meaningful state, committing it can help you switch tasks safely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. After completing a meaningful development step&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, you may first create the database model, then add the service logic, and finally connect it to the API.&lt;/p&gt;

&lt;p&gt;Each step can have its own commit if it is complete and useful on its own.&lt;/p&gt;

&lt;h3&gt;
  
  
  When should you avoid committing?
&lt;/h3&gt;

&lt;p&gt;Avoid creating normal commits that contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unrelated changes from different tasks.&lt;/li&gt;
&lt;li&gt;Unnecessary debugging logs.&lt;/li&gt;
&lt;li&gt;Accidentally included &lt;code&gt;.env&lt;/code&gt; files or credentials.&lt;/li&gt;
&lt;li&gt;Temporary files that should not be tracked.&lt;/li&gt;
&lt;li&gt;Half-finished changes that break the shared branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, work-in-progress commits are sometimes useful on personal feature branches. The important thing is to keep shared project history understandable.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Why Should We Commit Regularly?
&lt;/h2&gt;

&lt;p&gt;Some developers wait until they finish a large feature before creating a commit.&lt;/p&gt;

&lt;p&gt;That can make things difficult later.&lt;/p&gt;

&lt;p&gt;Here are some reasons to commit regularly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to understand&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Small commits tell you exactly what changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to review&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Other developers can review smaller changes without going through hundreds of unrelated lines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to undo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a particular change causes a problem, you can revert that commit without removing unrelated work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy to debug&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Git has a useful command called &lt;code&gt;git bisect&lt;/code&gt;. It helps find which commit introduced a bug.&lt;/p&gt;

&lt;p&gt;This works best when commits represent clear and complete changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better project history&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to understand how your project has changed over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Bad vs Good Commit Messages
&lt;/h2&gt;

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

&lt;p&gt;Let's compare some common examples.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bad commit message&lt;/th&gt;
&lt;th&gt;Better commit message&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fixed stuff&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fix(cart): prevent negative quantity&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;update&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;feat(auth): add Google login&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;changes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;refactor(api): extract validation logic&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;final version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs(readme): update setup guide&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bug fixed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fix(payment): handle failed transactions&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;new things&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;feat(user): add profile update&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code update&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style(ui): format React components&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The better messages tell us what changed without opening the code.&lt;/p&gt;

&lt;p&gt;That is the main goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Commit Types and Semantic Versioning
&lt;/h2&gt;

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

&lt;p&gt;Conventional Commits can also help with software version management.&lt;/p&gt;

&lt;p&gt;Many projects use Semantic Versioning, which follows this format:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Here is how the main commit types relate to version changes when using a compatible release setup.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Commit&lt;/th&gt;
&lt;th&gt;Version change&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;1.0.0 to 1.0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MINOR&lt;/td&gt;
&lt;td&gt;1.0.0 to 1.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breaking change&lt;/td&gt;
&lt;td&gt;MAJOR&lt;/td&gt;
&lt;td&gt;1.0.0 to 2.0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A breaking change can be marked using &lt;code&gt;!&lt;/code&gt; or &lt;code&gt;BREAKING CHANGE:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tools such as &lt;code&gt;semantic-release&lt;/code&gt; and &lt;code&gt;release-please&lt;/code&gt; can read commit messages and help generate changelogs and releases.&lt;/p&gt;

&lt;p&gt;One important thing: these version changes depend on your release tool and its configuration. Git itself does not automatically increase version numbers based on commit types.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. How to Follow These Rules Automatically
&lt;/h2&gt;

&lt;p&gt;Remembering all these rules can take time.&lt;/p&gt;

&lt;p&gt;Fortunately, there are tools that can check commit messages for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  commitlint
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;commitlint&lt;/code&gt; checks whether your commit messages follow the selected convention.&lt;/p&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @commitlint/cli @commitlint/config-conventional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// commitlint.config.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your project uses ES modules, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// commitlint.config.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Husky
&lt;/h3&gt;

&lt;p&gt;Husky allows you to run Git hooks automatically.&lt;/p&gt;

&lt;p&gt;Install and initialize it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky

npx husky init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a file named &lt;code&gt;.husky/commit-msg&lt;/code&gt; with this content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;--no&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; commitlint &lt;span class="nt"&gt;--edit&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when you create a commit, commitlint checks the message.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fixed stuff"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The commit will be rejected if the message does not follow your configured rules.&lt;/p&gt;

&lt;p&gt;But this message should pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix(auth): handle expired tokens"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  commitizen
&lt;/h3&gt;

&lt;p&gt;If you prefer answering questions instead of writing commit messages manually, you can use Commitizen.&lt;/p&gt;

&lt;p&gt;It guides you through the process of choosing a type, scope, and description.&lt;/p&gt;

&lt;p&gt;Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; commitizen cz-conventional-changelog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will help you create a properly formatted commit message.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Useful Git Commands Before Committing
&lt;/h2&gt;

&lt;p&gt;Before creating a commit, I recommend checking your changes.&lt;/p&gt;

&lt;p&gt;Here are some useful commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check changed files:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Review your changes:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stage the files you want to commit:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also stage a specific file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add src/controllers/auth.controller.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Review staged changes:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff &lt;span class="nt"&gt;--cached&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a commit:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(auth): add email verification"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;View recent commits:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;View detailed commit history:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more useful command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It allows you to select specific parts of a file instead of staging the entire file.&lt;/p&gt;

&lt;p&gt;This is helpful when one file contains changes from different tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Common Commit Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;Here are some mistakes developers should try to avoid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using &lt;code&gt;chore&lt;/code&gt; for everything&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every change is maintenance. Choose the type that describes the actual work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing very long subject lines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep the first line short. Add more details in the body when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mixing unrelated changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Do not combine a payment bug fix and a dashboard redesign in one commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Committing sensitive information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never commit passwords, API keys, private tokens, or production credentials.&lt;/p&gt;

&lt;p&gt;If a secret has already been pushed, removing it from the latest commit is not enough. You should rotate or revoke that secret immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Committing without checking staged files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Always review what you are about to commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating commits with unclear messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Avoid messages such as &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;changes&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt;, and &lt;code&gt;final&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A little extra time spent writing a clear message can save a lot of time later.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. A Simple Commit Message Cheat Sheet
&lt;/h2&gt;

&lt;p&gt;Here is a quick reference you can keep for your next project.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;New feature&lt;/td&gt;
&lt;td&gt;&lt;code&gt;feat(auth): add Google login&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bug fix&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fix(cart): prevent negative quantity&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs(readme): update setup guide&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Code formatting&lt;/td&gt;
&lt;td&gt;&lt;code&gt;style(ui): format components&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Code restructuring&lt;/td&gt;
&lt;td&gt;&lt;code&gt;refactor(api): extract middleware&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;perf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Performance improvement&lt;/td&gt;
&lt;td&gt;&lt;code&gt;perf(db): optimize queries&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Test changes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test(user): add signup tests&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build and dependencies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;build(deps): update packages&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ci&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CI/CD changes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ci: add GitHub Actions workflow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;General maintenance&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chore: update gitignore&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;revert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Undo a previous commit&lt;/td&gt;
&lt;td&gt;&lt;code&gt;revert: remove login feature&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Additional team-specific conventions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Initial project setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Work in progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;merge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Merge-related commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;release&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Release preparation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;improvement&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;General improvement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  16. My Checklist Before Every Commit
&lt;/h2&gt;

&lt;p&gt;Before creating a commit, check these things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Does this commit contain one logical change?&lt;/li&gt;
&lt;li&gt;[ ] Did I review the changed files?&lt;/li&gt;
&lt;li&gt;[ ] Did I check the staged changes?&lt;/li&gt;
&lt;li&gt;[ ] Did I choose the correct commit type?&lt;/li&gt;
&lt;li&gt;[ ] Is the commit message clear?&lt;/li&gt;
&lt;li&gt;[ ] Did I avoid unrelated changes?&lt;/li&gt;
&lt;li&gt;[ ] Did I exclude passwords and API keys?&lt;/li&gt;
&lt;li&gt;[ ] Did I run the relevant tests?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need to follow every rule perfectly from day one. Start with clear messages and small commits. Build the habit over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Writing good commit messages is a small habit, but it makes a real difference when working on software projects.&lt;/p&gt;

&lt;p&gt;You do not need to write long messages or use complicated words. Just explain what changed and choose the right commit type.&lt;/p&gt;

&lt;p&gt;When you work with other developers, a clean Git history makes everyone's job easier.&lt;/p&gt;

&lt;p&gt;Start using &lt;code&gt;feat&lt;/code&gt;, &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;docs&lt;/code&gt;, &lt;code&gt;refactor&lt;/code&gt;, and the other commit types in your next project.&lt;/p&gt;

&lt;p&gt;Your future self will thank you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the most unusual commit message you have ever written or seen?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Share it in the comments&lt;/p&gt;

&lt;p&gt;Happy coding&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>softwareengineering</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
