<?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: Paras 🧙‍♂️</title>
    <description>The latest articles on DEV Community by Paras 🧙‍♂️ (@paras594).</description>
    <link>https://dev.to/paras594</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F137802%2Fd0ae92c1-d7b4-4a4c-810e-7129d72f344c.jpg</url>
      <title>DEV Community: Paras 🧙‍♂️</title>
      <link>https://dev.to/paras594</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paras594"/>
    <language>en</language>
    <item>
      <title>Create small stuff.</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Fri, 23 Jan 2026 08:12:14 +0000</pubDate>
      <link>https://dev.to/paras594/create-small-stuff-119m</link>
      <guid>https://dev.to/paras594/create-small-stuff-119m</guid>
      <description>&lt;p&gt;If you’ve ever stopped yourself from building something because it felt too small, this is for you.&lt;/p&gt;

&lt;p&gt;I think we all get stuck at some point on the idea that whatever we build has to be big and meaningful. Often, that pressure comes from our own expectations.&lt;/p&gt;

&lt;p&gt;But this one is to remind you about the fun of building small stuff. &lt;br&gt;
No pressure, no expectations, just experimentation. &lt;/p&gt;

&lt;p&gt;You make it because something intrigues you. Maybe because something out there is not on par with your requirements. Maybe you just want to learn or try replicating it. Or to have fun in general. &lt;/p&gt;

&lt;p&gt;I remember when I started learning web dev, I had a lot of fun following html css tutorials and learning to build things with html css. Small animations, effects, and even css art. One can say I wasted my time and it's not used in the day to day life. But I still did it because it was fun for me. It didn't drive me away from development, instead brought me closer. &lt;/p&gt;

&lt;p&gt;And honestly, you're allowed to build things that don't matter to anyone else. Give yourself permission and the freedom. Try not to get stuck only on “big” ideas.&lt;/p&gt;

&lt;p&gt;Sometimes the best projects are the ones with no expectations attached.&lt;/p&gt;

&lt;p&gt;Here are a few small things that I made, and how they helped me in unexpected ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/paras594/react-starter-template" rel="noopener noreferrer"&gt;React starter template&lt;/a&gt;: I made it for myself to save time on new project. I keep improving it as I use it more and more. I quite like this. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/paras594/echoday" rel="noopener noreferrer"&gt;Echoday&lt;/a&gt;: A small project I made during Kendo react challenge on dev.to. And interestingly enough, it helped me in one my interviews :p&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/paras594/Minesweeper" rel="noopener noreferrer"&gt;Minesweeper&lt;/a&gt;: An old project of mine. I actually learned how to play Minesweeper properly because of it, and now I love the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope it made you think a bit about your ideas and projects. &lt;/p&gt;

&lt;p&gt;Thank you :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/paras594/" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/paras594/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt; &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Web Accessibility Reference Guide</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Mon, 29 Dec 2025 09:56:41 +0000</pubDate>
      <link>https://dev.to/paras594/web-accessibility-reference-guide-j08</link>
      <guid>https://dev.to/paras594/web-accessibility-reference-guide-j08</guid>
      <description>&lt;p&gt;Hey everyone, &lt;/p&gt;

&lt;p&gt;Recently I put together this web accessibility reference guide repo. &lt;/p&gt;

&lt;p&gt;It highlights key things to watch out for when building web UIs, like keyboard support, semantics, and focus behavior.&lt;/p&gt;

&lt;p&gt;It’s a collection of accessibility checks I personally find important and easy to miss or forget. &lt;/p&gt;

&lt;p&gt;I also added some HTML, CSS, and javascript examples that focus on keyboard accessibility. &lt;/p&gt;

&lt;p&gt;Github repo: &lt;a href="https://github.com/paras594/web-accessibility-guide" rel="noopener noreferrer"&gt;https://github.com/paras594/web-accessibility-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to bookmark it or star the repo so it’s easy to come back to when needed.&lt;/p&gt;

&lt;p&gt;Also if you find anything that can enhance it, you can share it in the comments or raise a PR on the repo. &lt;/p&gt;

&lt;p&gt;Thank you. Hope it helps.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>beginners</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Checklist for Engineers Joining a New Project</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Fri, 04 Jul 2025 08:33:50 +0000</pubDate>
      <link>https://dev.to/paras594/checklist-for-engineers-joining-a-new-project-4c08</link>
      <guid>https://dev.to/paras594/checklist-for-engineers-joining-a-new-project-4c08</guid>
      <description>&lt;p&gt;&lt;strong&gt;Goal&lt;/strong&gt;: A quick-reference checklist of dos and don'ts when you're new to a team or project - technical, cultural, and strategic.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bookmark this for future reference&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mindset
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listen and absorb&lt;/strong&gt; as much as you can from discussions, meetings and conversations. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask a lot of questions&lt;/strong&gt; from different people in your team such as engineers, PMs, QA, designers. Do not limit yourself to just your domain. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear assumptions:&lt;/strong&gt; It's good to clarify your assumptions even if they are obvious. &lt;/li&gt;
&lt;li&gt;Focus on &lt;strong&gt;"why X is like that"&lt;/strong&gt; instead of "why we are not doing Y instead of X". Understanding the context matters more than proposing alternatives early on. &lt;/li&gt;
&lt;li&gt;Start small: &lt;strong&gt;Ship a tiny fix or feature&lt;/strong&gt; to learn the end to end flow. Take notes where required to have a reference for next time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ramp up smartly
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Learn&lt;/strong&gt;&lt;br&gt;
✅ How to &lt;strong&gt;build, run, test and debug&lt;/strong&gt; the project locally. &lt;br&gt;
✅ Where &lt;strong&gt;docs live&lt;/strong&gt; (internal wikis, Notion, READMEs, Slack pins)&lt;br&gt;
✅ What is the &lt;strong&gt;API setup, data flow, and connection&lt;/strong&gt; between frontend and backend&lt;br&gt;
✅ Project &lt;strong&gt;structure, conventions, auth, permissions&lt;/strong&gt;, and environment variables&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release process&lt;/strong&gt;&lt;br&gt;
Understand the &lt;strong&gt;release process&lt;/strong&gt; — what happens after you push code? How can you verify your changes? Is there a &lt;strong&gt;post-deployment checklist&lt;/strong&gt; or test plan you need to follow? &lt;/p&gt;

&lt;p&gt;This helps you build confidence in the full development lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get familiar with&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub workflow (branches, PRs, reviews)&lt;/li&gt;
&lt;li&gt;Jira / PM tool workflow (tickets, estimations, priorities)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Know the Business + Team Culture
&lt;/h2&gt;

&lt;p&gt;Understanding the &lt;strong&gt;“why”&lt;/strong&gt; behind decisions and the way your team works helps you navigate smarter and contribute meaningfully. This helps you get the bigger picture.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What business value does the tech serve?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;business goals&lt;/strong&gt; are driving the current direction?&lt;/li&gt;
&lt;li&gt;Why &lt;em&gt;not&lt;/em&gt; switching tech is often a conscious, valid choice&lt;/li&gt;
&lt;li&gt;Understand legacy: it exists for a reason, even if it looks messy&lt;/li&gt;
&lt;li&gt;Learn the team’s &lt;strong&gt;communication norms&lt;/strong&gt;, review style, meeting rituals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Expectations Over Time
&lt;/h2&gt;

&lt;p&gt;Have realistic expectations for yourself based on the project’s size and complexity. A project is a marathon, not a sprint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ramp-up:&lt;/strong&gt; 3–6 months to be confident, especially in large/legacy projects &lt;br&gt;
&lt;strong&gt;Efficiency:&lt;/strong&gt; 1–2 years to become fast and intuitive &lt;br&gt;
&lt;strong&gt;Proficiency:&lt;/strong&gt; 3–5 years to develop deep technical and domain depth &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Take your time learning — there’s no rush to “prove yourself.”&lt;/li&gt;
&lt;li&gt;Ship something small, build confidence.&lt;/li&gt;
&lt;li&gt;Have fun and bring your unique value to the team.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>A React Starter Template for the Impatient Developer</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Fri, 04 Jul 2025 06:17:21 +0000</pubDate>
      <link>https://dev.to/paras594/a-react-starter-template-for-the-impatient-developer-455a</link>
      <guid>https://dev.to/paras594/a-react-starter-template-for-the-impatient-developer-455a</guid>
      <description>&lt;p&gt;I recently created a starter template and wanted to share the process behind it.&lt;/p&gt;

&lt;p&gt;If you're not interested in the process, here's the link: &lt;a href="https://github.com/paras594/react-starter-template" rel="noopener noreferrer"&gt;paras594/react-starter-template&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those who are interested, read ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I like building projects for fun and experimentation, but I always had one main problem: project setup. I've become well-versed in it and have no fear of getting started, but it's inefficient and damn slow. It slows me down that I have to spend a chunk of my time on setup instead of actually building the project.&lt;/p&gt;

&lt;p&gt;Sometimes I used Next.js for its defaults with routing, data fetching, and optimizations out of the box. Other times I went with custom setups and Vite. In the past I was dabbling with webpack and custom configurations, but with time it all changed and I never finalized one single approach.&lt;/p&gt;

&lt;p&gt;Even though I always thought of building templates I could reuse, I either didn't get the time or was too focused on the project that I let the templating part slip—until now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;I found &lt;a href="https://www.npmjs.com/package/degit?ref=ghost.org" rel="noopener noreferrer"&gt;&lt;strong&gt;degit&lt;/strong&gt;&lt;/a&gt; out of nowhere. I knew about it but never gave enough thought to it. But this time I understood my goal: have a template setup and add degit to the whole thing.&lt;/p&gt;

&lt;p&gt;I quickly sat down, used the &lt;a href="https://vite.dev/guide/" rel="noopener noreferrer"&gt;Vite + React&lt;/a&gt; default template, and invested time in a few key decisions on what to include.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Goals with the Template
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexible and extensible&lt;/strong&gt; - Should adapt to different project needs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliable folder structure&lt;/strong&gt; - Something you get familiar with over time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formatting and linting support&lt;/strong&gt; - Without requiring tons of configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling and components&lt;/strong&gt; - Easy to get started with&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Made the Cut
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vite.dev/guide/" rel="noopener noreferrer"&gt;&lt;strong&gt;Vite + React&lt;/strong&gt;&lt;/a&gt; - Fast builds and development server&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tanstack.com/router/latest" rel="noopener noreferrer"&gt;&lt;strong&gt;TanStack Router&lt;/strong&gt;&lt;/a&gt; - File-based routing with better type safety&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;&lt;strong&gt;TanStack Query&lt;/strong&gt;&lt;/a&gt; - Data fetching &amp;amp; server state management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt; + &lt;a href="https://daisyui.com/" rel="noopener noreferrer"&gt;DaisyUI&lt;/a&gt;&lt;/strong&gt; - Utility-first styling with ready-to-use components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://biomejs.dev/" rel="noopener noreferrer"&gt;Biome&lt;/a&gt;&lt;/strong&gt; - Linting and formatting&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/a&gt; - Type safety&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vite-pwa-org.netlify.app/" rel="noopener noreferrer"&gt;&lt;strong&gt;PWA support&lt;/strong&gt;&lt;/a&gt; - Progressive web app features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The goal was simple&lt;/strong&gt;: clone the repo and start building features on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Choices?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Vite is fast, &lt;/li&gt;
&lt;li&gt;TanStack Router provides a cleaner approach to handling routing than React Router, &lt;/li&gt;
&lt;li&gt;TanStack Query takes care of all the boilerplate that comes with data fetching, &lt;/li&gt;
&lt;li&gt;Tailwind + DaisyUI gives great default components without writing tons of classes, &lt;/li&gt;
&lt;li&gt;Biome avoids the hassle of keeping ESLint and Prettier updated while eliminating config bloat.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Evolves
&lt;/h2&gt;

&lt;p&gt;I actually use this template for my own projects, which means it stays current with my real-world needs. Dependabot keeps the dependencies updated, and I add or remove things as I encounter them in actual development.&lt;/p&gt;

&lt;p&gt;I'm also considering branches for different use cases - maybe a minimal version, or branches with specific additions like authentication or database integration. The idea is to have options without bloating the main template.&lt;/p&gt;

&lt;p&gt;The template is on GitHub: &lt;a href="https://github.com/paras594/react-starter-template" rel="noopener noreferrer"&gt;paras594/react-starter-template&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the steps in &lt;strong&gt;README&lt;/strong&gt; and you are good to go. &lt;/p&gt;

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

&lt;p&gt;This template isn't revolutionary - it's just a collection of tools that work well together and let you focus on building features instead of configuration. Feel free to use it if it matches what you usually reach for, or ignore it if your stack is different.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>EchoDay: Capture and reflect on your day</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Sat, 22 Mar 2025 05:32:57 +0000</pubDate>
      <link>https://dev.to/paras594/echoday-capture-and-reflect-on-your-day-3gik</link>
      <guid>https://dev.to/paras594/echoday-capture-and-reflect-on-your-day-3gik</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/kendoreact"&gt;KendoReact Free Components Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;EchoDay is a web app centered around daily reflection, where each day feels like an echo. Whatever you add - notes, memories, or thoughts - comes back to you later, helping you revisit and reflect on moments that matter. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;br&gt;
It features a set of handy widgets - one place to store them all.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Calendar to plan your schedule&lt;/li&gt;
&lt;li&gt;Notes for jotting down ideas&lt;/li&gt;
&lt;li&gt;An About My Day section to reflect on your day&lt;/li&gt;
&lt;li&gt;Todos list to stay on top of tasks&lt;/li&gt;
&lt;li&gt;Reminders, so you never miss anything&lt;/li&gt;
&lt;li&gt;Memories, where you store cherished images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oh, it also has a little mood tracker with some fun emojis and moods to choose from :)&lt;/p&gt;

&lt;p&gt;Right now, it’s a prototype, but if people love it, we are planning to add a fully functional backend to make it even more dynamic. It’s a simple idea, but one we think can make life a lot more organized and meaningful! &lt;/p&gt;

&lt;p&gt;Do share your review in the app. We have included a user review section at the bottom. &lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;Demo Link: &lt;a href="https://echoday.netlify.app" rel="noopener noreferrer"&gt;EchoDay&lt;/a&gt;&lt;br&gt;
Github Repo: &lt;a href="https://github.com/paras594/echoday" rel="noopener noreferrer"&gt;EchoDay Repo&lt;/a&gt;&lt;br&gt;
UI/UX Case Study: &lt;a href="https://www.behance.net/gallery/229803121/EchoDay-Capture-and-Reflect-on-your-day" rel="noopener noreferrer"&gt;Behance Case Study&lt;/a&gt;&lt;/p&gt;

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

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

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

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

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

&lt;h2&gt;
  
  
  Components Used
&lt;/h2&gt;

&lt;p&gt;Here is a list for reference for the components used in the project&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grid&lt;/li&gt;
&lt;li&gt;Icons &amp;amp; Loader&lt;/li&gt;
&lt;li&gt;Input &amp;amp; TextArea&lt;/li&gt;
&lt;li&gt;StackLayout&lt;/li&gt;
&lt;li&gt;Typography&lt;/li&gt;
&lt;li&gt;Card&lt;/li&gt;
&lt;li&gt;AppBar&lt;/li&gt;
&lt;li&gt;Avatar&lt;/li&gt;
&lt;li&gt;Rating&lt;/li&gt;
&lt;li&gt;Button and more.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Thanks to My Teammate
&lt;/h3&gt;

&lt;p&gt;A heartfelt thanks to &lt;a href="https://www.behance.net/muskaanarora10" rel="noopener noreferrer"&gt;Muskan&lt;/a&gt; for beautifully designing the web app and making the most of the KendoReact Figma UI Kit. Your creativity and attention to detail truly shine through!&lt;/p&gt;

&lt;h2&gt;
  
  
  KendoReact Experience
&lt;/h2&gt;

&lt;p&gt;KendoReact is a fun UI library to work with. It provided a wide range of pre-built, customizable components that made the development process smooth and efficient. Features like layout components, grid, icons, typography and popups saved a ton of time and allowed me to focus more on functionality and user experience. &lt;/p&gt;

&lt;p&gt;One of the standout features was the ability to install only the necessary packages. This not only kept the project lightweight but also made managing dependencies much easier.&lt;/p&gt;

&lt;p&gt;However, I found the documentation could use improvement. While it covers the basics well, certain advanced features lacked detailed explanations, and some examples were too generic to be practically helpful. &lt;/p&gt;




&lt;p&gt;In conclusion, building this app was a rewarding experience. Using KendoReact was a delight in this project. Even the free version provided enough components out of the box. Overall, it was a valuable journey, thanks to KendoReact and Dev.to team for hosting this fun challenge. &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>kendoreactchallenge</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Project: Echopad</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Sun, 16 Jun 2024 08:33:32 +0000</pubDate>
      <link>https://dev.to/paras594/project-echopad-37jc</link>
      <guid>https://dev.to/paras594/project-echopad-37jc</guid>
      <description>&lt;p&gt;Hey Guys, &lt;/p&gt;

&lt;p&gt;Excited to share my latest project - EchoPad. A powerful web app that helps you sync texts, links &amp;amp; files seamlessly across devices in real-time and enjoy hassle-free file management. &lt;/p&gt;

&lt;p&gt;🔗 EchoPad: &lt;a href="https://echopad.vercel.app/" rel="noopener noreferrer"&gt;https://echopad.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register &amp;amp; Login on EchoPad.&lt;/li&gt;
&lt;li&gt;Type in your block of text, links or upload some files using file manager.&lt;/li&gt;
&lt;li&gt;Access your account on another device &amp;amp; there you have your data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;❓Why use EchoPad?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No need to email yourself links, files &amp;amp; texts.&lt;/li&gt;
&lt;li&gt;No need to rely on messaging apps to share files across devices. &lt;/li&gt;
&lt;li&gt;No need to login your personal accounts &amp;amp; mails on some other device. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And to make it convenient, you can install it and use it like any other app on your device. &lt;/p&gt;

&lt;p&gt;⏩ Stay tuned for upcoming features! I am continuously improving and refining the EchoPad. &lt;/p&gt;

&lt;h3&gt;
  
  
  Technical aspects of project
&lt;/h3&gt;

&lt;p&gt;It's a small Progressive Web App, built using React, Node, Express and MongoDB. Socket.io is also used to help sync data in real time to avoid saving and refreshing data manually in multiple devices. It also supports file upload to be able share some small files across devices. To save some space, files get deleted after 24hrs. &lt;/p&gt;

&lt;p&gt;Apart from this, there is not much to it. It's a simple web app. Give it a try and share your thoughts. &lt;/p&gt;

&lt;h4&gt;
  
  
  Other posts by me
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://dev.to/paras594/basics-of-caching-139l"&gt;Basics of caching &amp;amp; caching in depth&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/paras594/what-can-we-learn-from-bootstrap-css-42ll"&gt;What can we learn from bootstrap css&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/paras594/create-stopwatch-with-c-46bp"&gt;Create stopwatch using C++&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>product</category>
      <category>pwa</category>
    </item>
    <item>
      <title>What can we learn from Bootstrap CSS</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Mon, 27 May 2024 09:59:40 +0000</pubDate>
      <link>https://dev.to/paras594/what-can-we-learn-from-bootstrap-css-42ll</link>
      <guid>https://dev.to/paras594/what-can-we-learn-from-bootstrap-css-42ll</guid>
      <description>&lt;p&gt;The world of programming has changed a lot. There was a time when writing code was like an art. Principles of programming were the backbone of any software. They are still there, but due to the shift in technology, pace of projects, and change of mindset, we have drifted away from those fundamentals. &lt;/p&gt;

&lt;p&gt;I want to show how technologies around us still utilize these fundamentals and doing great in market. One of them is &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap CSS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's why I have decided to share my observations on Bootstrap CSS. It's not that great now and there are other frameworks but let's see what Bootstrap does right and what we can learn from it.&lt;/p&gt;

&lt;p&gt;So, let's begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the basic design of bootstrap
&lt;/h2&gt;

&lt;p&gt;Bootstrap is based around css classes. It's filled with components that are reusable and composable. Then, it has classes for building layouts, range of form components, some helpers and then some utilities. By combining them all, we can build good looking, functional and user friendly web pages very quickly. &lt;/p&gt;

&lt;p&gt;But what can we even learn from Bootstrap? Let's find out!&lt;/p&gt;

&lt;h2&gt;
  
  
  Principles of programming in Bootstrap?!
&lt;/h2&gt;

&lt;p&gt;It may not seem at first glance, but bootstrap is using many common programming principles in front of our eyes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KISS: Keep It Simple, Stupid&lt;/li&gt;
&lt;li&gt;DRY&lt;/li&gt;
&lt;li&gt;Single Responsibility Principle&lt;/li&gt;
&lt;li&gt;Separation of Concerns&lt;/li&gt;
&lt;li&gt;Law of Demeter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;KISS: Keep It Simple, Stupid&lt;/strong&gt;&lt;br&gt;
Bootstrap is quite simple to pick and learn. Once you understand how they have structured the framework, it's easy to get up and running with. Need a button? Add &lt;code&gt;btn&lt;/code&gt; class and it's done. Worried about responsiveness? Got you covered with media query utilities. And that's how Bootstrap utilizes our first principle. &lt;/p&gt;

&lt;p&gt;Learning: Keep your code simple and to the point. Overengineering only adds complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DRY: Don't Repeat Yourself&lt;/strong&gt;&lt;br&gt;
When we first start learning CSS, we tend to write a lot of duplicate stylings, classes etc. But in Bootstrap, we have these component classes that helps us avoid writing duplicate css. If there are two cards in different sections, it's most likely that we are using the same &lt;code&gt;card&lt;/code&gt; class in both of them and making small adjustments as per requirement. &lt;/p&gt;

&lt;p&gt;Learning: Try to avoid duplicate code and leverage functions, classes, utilities to create reusable components. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single Responsibility Principle: (S in SOLID)&lt;/strong&gt;&lt;br&gt;
Every single class in Bootstrap has one responsibility and one function. A &lt;code&gt;btn&lt;/code&gt; class is only designed to build button structure. It is not adding extra margins around and doing some crazy stuff with sibling elements. A &lt;code&gt;container&lt;/code&gt; class is only responsible for keeping content in center and in a container, nothing more. Same goes for &lt;code&gt;row&lt;/code&gt; class, &lt;code&gt;margin&lt;/code&gt; utilities etc. It avoids a ton of complexity in building layouts. &lt;/p&gt;

&lt;p&gt;Learning: This principle is easy to understand but hard to master. Make sure your components and entities are not fulfilling multiple responsibilities. One entity equals to one responsibility.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(SoC) Separation of Concerns&lt;/strong&gt;&lt;br&gt;
A component in Bootstrap doesn't interfere with another component directly. Each component, layout class, utility and helper, addresses a specific concern and has a specific job. A &lt;code&gt;container&lt;/code&gt; class is independent of &lt;code&gt;row&lt;/code&gt; class. &lt;code&gt;row&lt;/code&gt; class handles the 12-column grid system, and &lt;code&gt;container&lt;/code&gt; class is concerned with only centering and specifying width of content. Imagine a class that is a mix of both (I know you have written such CSS, because we all do)&lt;/p&gt;

&lt;p&gt;Learning: Avoid mixing concerns and features. Try to divide it in chunks such that each chunks solves a particular problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Law of Demeter: The principle of least knowledge&lt;/strong&gt;&lt;br&gt;
This one was new for me. The Law of Demeter says that each component should have only limited knowledge of other components. So, if something is closely related to a component, it can have a limited knowledge of it, but not any stranger component. "Only talk to your immediate friends"&lt;br&gt;
In bootstrap, &lt;code&gt;form&lt;/code&gt; components and classes only affect form related components, or a &lt;code&gt;btn&lt;/code&gt; modifier class only affects a &lt;code&gt;btn&lt;/code&gt; and not any other entity. &lt;/p&gt;

&lt;p&gt;Learning: Take every parameter as an info. Entity which needs the info, is the only one to have the info and not anyone in between. This also simplifies testing and makes code more readable. &lt;/p&gt;




&lt;p&gt;So, these are some of the points that I observed, and I am sure there are many other things that I have not noticed just yet. If a CSS framework can apply these principles and become the most used framework, then maybe we can also take a step back and try to apply these principles that not only solves the problem at hand but also adds value to our projects. &lt;/p&gt;

&lt;p&gt;Even today, there are gems from which we can learn and improve our understanding. Open source is filled with such learnings. I encourage everyone to read other's code, understand their approach and try to apply the same and see how it helps and how you can improve. &lt;/p&gt;

&lt;p&gt;That's it for this one. Hope you find it helpful. Feel free to share your observations!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>css</category>
    </item>
    <item>
      <title>Caching in depth</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Fri, 26 Apr 2024 09:01:18 +0000</pubDate>
      <link>https://dev.to/paras594/caching-in-depth-5abj</link>
      <guid>https://dev.to/paras594/caching-in-depth-5abj</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/paras594/basics-of-caching-139l"&gt;previous post&lt;/a&gt; we learned about what is caching and why it's useful. Now, we are going to understand some more concepts related to caching. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topics Covered&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Comparison with different databases&lt;/li&gt;
&lt;li&gt;  Cache eviction policies&lt;/li&gt;
&lt;li&gt;  Cache miss&lt;/li&gt;
&lt;li&gt;  Cache invalidation strategies&lt;/li&gt;
&lt;li&gt;  Challenges with caching&lt;/li&gt;
&lt;li&gt;  Cache metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When working with caching database, it may seem a simple task to store the frequently accessed data in cache and retrieve on subsequent calls instead of hitting our main DB. But, it's not that simple.&lt;/p&gt;

&lt;p&gt;What if your cache storage is full, and you want to get rid of unnecessary cache data. In this case, how will you determine which data to be discarded and which data to be kept?&lt;/p&gt;

&lt;p&gt;What if the data requested is not in cache. Should you save this after fetching from main DB or not?&lt;/p&gt;

&lt;p&gt;What amount of your total data should you store in cache? How do you decide the storage size? &lt;/p&gt;

&lt;p&gt;These are some of the problems that we face when working with caching databases. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why cache DB like Redis or Memcached are faster than normal DB like Mongo or MySQL?
&lt;/h3&gt;

&lt;p&gt;Simple answer to this question is, cache databases are in-memory databases and do not store data on disk. On the other hand, databases like MySQL &amp;amp; Mongo store data on disk storage. And because RAM is faster than Disk, it is ideal to make reads &amp;amp; writes faster. &lt;/p&gt;

&lt;p&gt;But RAM is also more expensive, therefore, it requires some consideration on what data to store and what data to discard. &lt;/p&gt;

&lt;p&gt;In-Memory storage is not the only way, we can also choose to store cache in disk, CDN, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Eviction Policies
&lt;/h2&gt;

&lt;p&gt;Cache eviction policy is just deciding which data to discard and which data to keep when cache reaches its limit. &lt;/p&gt;

&lt;p&gt;The main benefit of doing this is, it optimizes our cache performance because we are removing unnecessary data. &lt;/p&gt;

&lt;p&gt;There are many policies available that we can choose from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;LRU (Least Recently Used)&lt;/strong&gt; - remove the data is used least frequently. This policy is based on the time. Example, if a user accesses a web page and is likely to visit it again, then it's a good idea to evict least recently used data.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;MRU (Most Recently Used)&lt;/strong&gt; - remove the most recently used data. Example, if a user watches a movie, it's less likely that he will watch it again, in this case, it's best to evict the most recently used cache.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LFU (Least Frequently Used)&lt;/strong&gt; - this policy is based on how frequently same data is being accessed. If a data is used less frequently by users, we evict it to make space for new data. Example, databases can cache the results of queries that are more frequently used. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;MFU (Most Frequently Used)&lt;/strong&gt; - this policy is the opposite of LFU and may seem unnecessary. But, there are times when this can be helpful. I don't have an example for this one, so if you have one, do share in comment :)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;FIFO (First In, First Out)&lt;/strong&gt; - remove the data that got added first, to make space for the new data. It's similar to a queue. One simple example can be browser history, in which the oldest item in the history is removed to make room for newly visited page. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LIFO (Last In, First Out)&lt;/strong&gt; - it may seem similar to MRU, but instead of considering the frequency, we just remove the most recent data from cache. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Size Based Eviction&lt;/strong&gt; - in applications where data is large in size, we may choose to discard data with the largest size and to make room for new data. This ensures that cache storage is not full just by storing a few amount of data. Example, in a CDN, we can choose to discard the data according to the size and frequency to ensure we have space in cache for future data. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Adaptive Replacement Cache&lt;/strong&gt; - this strategy of cache eviction is based on algorithm that dynamically decides which data to discard and which data to keep by observing the workload. It maintains a list of frequently used and recently used data. You can explore it in details as this strategy can provide great performance in various scenarios but may take some efforts to setup. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun Fact:&lt;/strong&gt; Caching is also used in problem solving and building efficient algorithms especially in Dynamic Programming. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What should be the size of our cache storage?
&lt;/h2&gt;

&lt;p&gt;Now that we have an idea of what options we can have to discard the data we need, next thing that we need to know is what should be the size of our cache storage.&lt;br&gt;
So, usually it depends on the use case and architecture of your system, but if you don't know what to start with, you can consider &lt;strong&gt;20% of Daily Traffic&lt;/strong&gt; as the amount of data to cache. Suppose your application has a traffic of around 10gb daily, then you can have the cache storage of 2gb. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's a cache miss??
&lt;/h2&gt;

&lt;p&gt;When you check the cache storage for data and you don't find one, that is called cache miss. This is when you make call to your main database to get the data and update cache. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Invalidation Strategies
&lt;/h2&gt;

&lt;p&gt;Cache invalidation is deciding when and how cached data should be considered stale or invalid. This makes that data no longer usable. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Difference b/w eviction and invalidation&lt;/strong&gt;&lt;br&gt;
The difference between cache invalidation and cache eviction is cache eviction is deciding what data to discard when cache storage is full, while cache invalidation is marking cache data as invalid. &lt;/p&gt;

&lt;p&gt;Benefits of Cache invalidation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache invalidation affects the consistency of data served to the user. &lt;/li&gt;
&lt;li&gt;Maintains up to date data in cache, consistent with our main database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Strategies
&lt;/h3&gt;

&lt;p&gt;There are many strategies for cache invalidation based on different factors that caters to different use cases: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Time Based:&lt;/strong&gt; In this strategy, we set an expiration on the cached data. Once the expiry is hit, data is marked as stale and we can either discard it or replace it with fresh data. It's a fairly simple and effective strategy. Key thing to keep in mind is to decide the expiration time. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write Through:&lt;/strong&gt; we update our cache and main database together when we receive new data. One example of this can be, suppose in a ecommerce website, products count can be updated in both cache and main database. Drawback of this strategy is that it increases the latency as data needs to be saved in cache and main DB before responding to user. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write Back:&lt;/strong&gt; This strategy can be applied in real time applications, where multiple users are collaborating. So, we start by storing the updates in cache storage, which results in faster reads and writes, and when a certain threshold is reached, we update the main database using our cache. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write Behind:&lt;/strong&gt; While write-back strategy waits for certain condition to trigger the update to main database, write-behind is based on eventually updating the main DB on specified intervals. Example, in online applications, data can be first written to cache, and can be stored in main database on specified intervals. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Based:&lt;/strong&gt; In this strategy, cache data is stored against a key, which can be a unique identifier or a group of relevant attributes. When there are changes to the actual data, such as delete or update, cached data is also marked as invalid to ensure users receive the most current information. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Challenges with caching
&lt;/h2&gt;

&lt;p&gt;Always keep in mind, whenever we introduce something in our system, however small it is, it always brings a level of complexity in our system. Same is true for caching. &lt;br&gt;
Caching may seem simple on surface but due to its versatile nature, it presents several challenges that we need to address to actually derive the value out of it. &lt;/p&gt;

&lt;p&gt;Let's see what are some common challenges with caching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache Invalidation:&lt;/strong&gt; Above, we discussed some of the strategies that are used for cache invalidation. But choosing the right one is not easy. Different architectures require different type of strategies. So, try to look at all the possible scenarios and monitor the cache and data to come up with the right strategy. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; You can use tools like &lt;a href="https://www.datadoghq.com/" rel="noopener noreferrer"&gt;DataDog&lt;/a&gt;, perf (Linux), &lt;a href="https://newrelic.com/" rel="noopener noreferrer"&gt;New Relic&lt;/a&gt; etc. to monitor cache performance&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Eviction:&lt;/strong&gt; Similar to cache invalidation, choosing the right cache eviction policy is crucial. Don't just go with Least Recently Used eviction policy by default. Analyze data and your system requirements and then decide the best policy. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Security:&lt;/strong&gt; Make sure your cache database is protected from unauthorized access. Therefore, implement proper access control and authentication system to ensure data privacy and integrity. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Expiration:&lt;/strong&gt; This can be one of the hardest thing to achieve. If you set a short expiration, your chances of cache miss will increase. And if you set a long expiration, your data will become stale and inconsistent with the DB. So, give this also some thought when setting this up. Discuss with your team and monitor your cache to eventually reach the sweet spot. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; The better you understand your application's data access patterns, the easier it is to setup your caching layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cache Metrics
&lt;/h2&gt;

&lt;p&gt;When trying to setup monitoring for your cache, there are a few metrics that you can focus on to get a better understanding. Our goal with cache metrics is to determine how well our caching strategy is performing under different workloads. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hit Ratio:&lt;/strong&gt; Also known as Cache Hit Rate, helps us evaluate how well our cache system is performing. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cache Hit Ratio(%) = (&lt;code&gt;Number of Cache Hits&lt;/code&gt; / &lt;code&gt;Total Number of Cache Accesses&lt;/code&gt;) * 100&lt;/p&gt;

&lt;p&gt;where, &lt;br&gt;
&lt;code&gt;Number of cache hits&lt;/code&gt; is the total number of cache hits where data was found in cache, and&lt;br&gt;
&lt;code&gt;Total Number of cache accesses&lt;/code&gt; is the total number of cache hits made&lt;/p&gt;

&lt;p&gt;Higher Hit Ratio means cache is used adequately and we are getting good performance by having reduced latency, better performance and less load on our backend. Cache Hit Ratio of &lt;code&gt;90-97%&lt;/code&gt; is ideal for a cache system. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Miss:&lt;/strong&gt; It is opposite of Cache Hit and indicates that higher number of requests are not utilizing cache properly. Thus, we should look into our application's data access pattern. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache Size:&lt;/strong&gt; We can also monitor how much cache size is actually used by our system. Having a larger cache size means higher Hit Rate but that also increases memory usage of our system and may incur extra cost. So, by monitoring data and adjusting cache size, we can reduce our cost and still keep our system performant. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In summary, it's crucial to analyze your requirements thoroughly and determine the caching strategy that best fits your needs. Applying these concepts may require time and effort, but understanding and incorporating them into your coding practices will prove invaluable in the long run. Thank you for reading, and I hope this information aids you in your coding journey.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>database</category>
      <category>coding</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Basics of Caching</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Wed, 13 Mar 2024 09:13:26 +0000</pubDate>
      <link>https://dev.to/paras594/basics-of-caching-139l</link>
      <guid>https://dev.to/paras594/basics-of-caching-139l</guid>
      <description>&lt;p&gt;Caching is one of the things that is key in improving the performance of any system. Doesn't matter if it is frontend, backend, CPUs or our day to day devices, you will find them using caching in one way or the other. And that's what we are going to learn in this two post series. &lt;/p&gt;

&lt;p&gt;First one will cover the basics of caching &amp;amp; second one will cover caching related concepts and advance stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we will be covering?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What &amp;amp; why of caching&lt;/li&gt;
&lt;li&gt;Different types of cache&lt;/li&gt;
&lt;li&gt;Caching in different layers with example&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Caching is saving the data temporarily, that you frequently access, in a storage i.e. cache, so that you don't need to make a complete request again to get the same data. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Temporary data&lt;/li&gt;
&lt;li&gt;Frequent Access&lt;/li&gt;
&lt;li&gt;Avoid complete requests for same data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cache storage are usually faster and available closer to the processing unit e.g. frontend, backend. &lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why we need Caching?
&lt;/h2&gt;

&lt;p&gt;We can understand the need of caching if we understand the key points above. &lt;/p&gt;

&lt;p&gt;Let's understand the problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our primary databases are usually slow and it takes time to retrieve data from them. &lt;/li&gt;
&lt;li&gt;Request for frequently accessed data adds unnecessary overhead to our server.&lt;/li&gt;
&lt;li&gt;In mission critical systems, loads on our server &amp;amp; database needs to be reduced.&lt;/li&gt;
&lt;li&gt;Some queries &amp;amp; API calls are expensive and computing them again and again is not optimal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, to keep above points in check, we add a layer of caching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of caching&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster access of data results in better user experience&lt;/li&gt;
&lt;li&gt;Reduces latency: No need to access main DB again for same data&lt;/li&gt;
&lt;li&gt;Reduces workload on main DB &amp;amp; server making it cost effective&lt;/li&gt;
&lt;li&gt;In many cases, because data is cached, it is available offline. &lt;/li&gt;
&lt;li&gt;Saves bandwidth &amp;amp; leads to low network traffic. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Different types of caches
&lt;/h2&gt;

&lt;p&gt;There are different types of caches that cater to different use cases. Example, a CPU needs different type of cache than a Frontend application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browser Caching
&lt;/h3&gt;

&lt;p&gt;Starting with frontend, we have browser level caching. Very useful for frontend application, as it reduces the need to make API calls to get the same for the user. &lt;/p&gt;

&lt;p&gt;When a user visits a page and gets the data, we save that data in browser cache and when same page is visited by the user, we read data from cache instead of making API call. We cache multiple things in frontend, e.g. API responses, Images, Videos, assets, user info etc. &lt;/p&gt;

&lt;p&gt;Apart from browser cache storage, we can also leverage Local Storage in browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN: Content Delivery Networks
&lt;/h3&gt;

&lt;p&gt;You can understand CDN as storage servers that are spread across globe and we can access data from the nearby CDN available. This avoids the need for making request to another region just to get the data. &lt;/p&gt;

&lt;p&gt;CDNs are mostly used for storing data like images, videos, audio, static files such as css, js etc, streaming content, and large files. E.g. AWS Cloudfront, Cloudinary, Akamai&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Server Cache
&lt;/h3&gt;

&lt;p&gt;This is the cache we add on our backend side of application. When we receive a request for some data, we fetch the data from our main database, save the data in cache (redis, memcached) for future users and return the response to user. &lt;/p&gt;

&lt;p&gt;When request for same data comes to server, we check if it exists in cache, if it does, we return the data directly. This helps reduce load on database and also makes requests faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database caching
&lt;/h3&gt;

&lt;p&gt;Databases also implement caching to improve query performance. Suppose there is a query which is frequently hit by multiple users. So, databases caches the result &amp;amp; plan for the query and returns the cached data in subsequent requests. &lt;/p&gt;

&lt;p&gt;This results in faster queries and reduces some load on DB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other types of caches
&lt;/h3&gt;

&lt;p&gt;There are other caches that are used in different scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CPU Cache&lt;/strong&gt;: L1 Cache (closest to CPU), L2 Cache (shared among CPU cores), L3 Cache (shared and has more size than L1 &amp;amp; L2)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Cache&lt;/strong&gt;: RAM Cache to speed up I/O operations. Disk Cache to speed up Reads/Writes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS Caching&lt;/strong&gt;: DNS also cache the IP addresses and other info related to Domain Name requests. E.g. AWS Route53&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Caching in different layers
&lt;/h2&gt;

&lt;p&gt;As we can see, caching can be utilized in various places. Let's discuss some examples and how we can leverage caching to improve our system. For simplicity, we will focus on Frontend scenarios and backend scenarios&lt;/p&gt;

&lt;p&gt;Here is our example:&lt;/p&gt;

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

&lt;p&gt;Components: We have our client, a load balancer to forward request to our servers, 2 API servers &amp;amp; 1 media server to send static content like images, files etc. and finally our database. &lt;/p&gt;

&lt;p&gt;Let's say we are trying to get a long list of products for our users and it's taking a good amount of time to receive the data from our database. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Issues in our current setup&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Because requested data is a long list of products, it is adding an overhead on our database. &lt;/li&gt;
&lt;li&gt;Servers can reach their limit if too many users start making requests. &lt;/li&gt;
&lt;li&gt;Not a good experience for client, because requests are taking time. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start solving these issues&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;&lt;br&gt;
First up, it's our backend side of application. &lt;br&gt;
We can add a caching layer to save the data retrieved from DB in cache storage. Then, when other users make the request for the list of products, instead of hitting our DB again, we will utilize our cached data and return that. &lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces load on database&lt;/li&gt;
&lt;li&gt;Makes future requests faster i.e. minimizes latency&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;br&gt;
Next, we can cache data in frontend on browser level. This way, if a user revisits the products page again, we don't need to refetch the products. &lt;/p&gt;

&lt;p&gt;There are libraries like Redux, React Query and other solutions, that help us store data locally so that we don't need make unnecessary requests to our server. &lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces load on our servers&lt;/li&gt;
&lt;li&gt;Better user experience&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Static Files&lt;/strong&gt;&lt;br&gt;
We can also improve our requests for static files. Currently, they are stored on our server. Let's assume users from different region are making requests for product images. Users from nearby region will be able to get the image faster than the users from another region. &lt;/p&gt;

&lt;p&gt;To handle this, we can utilize CDN (Content Delivery Networks). Because they are spread across globe, our data will be available close to our users. &lt;/p&gt;

&lt;p&gt;Thus, we will upload our static files in CDN.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Other Improvements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using pagination to reduce the amount of data requested&lt;/li&gt;
&lt;li&gt;Rate limiter to prevent excessive traffic or abuse by limiting the number of requests that can be processed within a specific time period&lt;/li&gt;
&lt;li&gt;Using multiple read replicas for our database&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some Popular Cache Databases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.memcached.org/" rel="noopener noreferrer"&gt;Memcached&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Google Cloud Memorystore&lt;/li&gt;
&lt;li&gt;AWS ElatiCache&lt;/li&gt;
&lt;li&gt;Amazon DynamoDB Accelerator (DAX)&lt;/li&gt;
&lt;li&gt;Azure Cache for Redis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CDN Services
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; (with a nice free plan for hobby projects)&lt;/li&gt;
&lt;li&gt;AWS CloudFront&lt;/li&gt;
&lt;li&gt;Azure CDN&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;So, this was it. I hope you learned something new about caching. Share your suggestions or any improvements in comments. In the next post, I will cover different concepts related to caching like cache eviction policies, cache invalidation strategies, challenges, scaling cache storage etc. &lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>interview</category>
      <category>tutorial</category>
      <category>database</category>
    </item>
    <item>
      <title>Upload images to AWS S3 using multer in node.js</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Wed, 13 Jul 2022 09:40:51 +0000</pubDate>
      <link>https://dev.to/paras594/upload-images-to-aws-s3-using-multer-in-nodejs-1164</link>
      <guid>https://dev.to/paras594/upload-images-to-aws-s3-using-multer-in-nodejs-1164</guid>
      <description>&lt;p&gt;Multer is a node.js middleware and it handles multipart/form-data that includes files, images etc. &lt;/p&gt;

&lt;p&gt;It mostly occurs in projects that we need to handle file uploads in our APIs. We can save those files in local disk storage on our system, but its better to have a hosted platform where we can upload our files and access through anywhere using the link. One such cloud storage is AWS S3. &lt;/p&gt;

&lt;p&gt;In this post, we will be uploading images to S3 storage using multer. Likewise, you can handle any kind of file you like. Also, we will learn to use the &lt;code&gt;version 3&lt;/code&gt; of AWS sdk, which has a little different setup than the previous version.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Basics of node.js and express &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup AWS Account
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create an account on AWS. &lt;/li&gt;
&lt;li&gt;There should be &lt;code&gt;services&lt;/code&gt; tab/link. From there, we can select &lt;code&gt;S3&lt;/code&gt;. It will be empty but we will be able to see objects in it once we start uploading files in it.&lt;/li&gt;
&lt;li&gt;Grab your access keys from your files in credentials section. You should have &lt;code&gt;access key id&lt;/code&gt; and &lt;code&gt;secret key&lt;/code&gt;. We will use these when configuring multer.&lt;/li&gt;
&lt;li&gt;Choose your AWS &lt;strong&gt;region&lt;/strong&gt; as per your location and take a note of its region id. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setup Multer
&lt;/h2&gt;

&lt;p&gt;To connect with AWS S3, we need its SDK and multer-s3 package. We will be using AWS SDK V3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Multer, multer-s3 and aws sdk&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;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; multer multer-s3 @aws-sdk/client-s3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create multer middleware&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your middlewares folder, create a file &lt;code&gt;uploadImage.js&lt;/code&gt;. You can name it anything you like. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: In &lt;code&gt;uploadImage.js&lt;/code&gt;, we will setup the S3 client:&lt;/strong&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;multer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multerS3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;multer-s3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// create s3 instance using S3Client &lt;/span&gt;
&lt;span class="c1"&gt;// (this is how we create s3 instance in v3)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;accessKeyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_ACCESS_KEY_ID_HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// store it in .env file to keep it safe&lt;/span&gt;
        &lt;span class="na"&gt;secretAccessKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_SECRET_KEY_HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ap-south-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// this is the region that you select in AWS account&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: In &lt;code&gt;uploadImage.js&lt;/code&gt;, add the following. use multer-s3 to connect to client and create s3 storage for multer&lt;/strong&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3Storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multerS3&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// s3 instance&lt;/span&gt;
    &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-images&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// change it as per your project requirement&lt;/span&gt;
    &lt;span class="na"&gt;acl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public-read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// storage access type&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldname&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fieldname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileName&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;&lt;strong&gt;Step 3: Using our storage instance to create our &lt;code&gt;uploadImage&lt;/code&gt; middleware using multer&lt;/strong&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="c1"&gt;// function to sanitize files and send error for unsupported files&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sanitizeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Define the allowed extension&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileExts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.gif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Check allowed extensions&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAllowedExt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fileExts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Mime type must be an image&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAllowedMimeType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mimetype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAllowedExt&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isAllowedMimeType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// no errors&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// pass error msg to callback, which can be displaye in frontend&lt;/span&gt;
        &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: File type not allowed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// our middleware&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uploadImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3Storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fileFilter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;sanitizeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;fileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// 2mb file size&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using uploadImage middleware in routes
&lt;/h2&gt;

&lt;p&gt;Lets create a route where a user can update his profile image. I assume express and router is already setup.&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;// update profile image&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:userId/profile-image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// our uploadImage middleware&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* 
           req.file = { 
             fieldname, originalname, 
             mimetype, size, bucket, key, location
           }
        */&lt;/span&gt;

        &lt;span class="c1"&gt;// location key in req.file holds the s3 url for the image&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// HERE IS YOUR LOGIC TO UPDATE THE DATA IN DATABASE&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;So, this was it for using multer with AWS and v3 SDK. I hope you find it helpful. &lt;/p&gt;

&lt;p&gt;✌️&lt;/p&gt;

</description>
      <category>node</category>
      <category>aws</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Node.js Morgan Guide</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Sat, 05 Jun 2021 16:26:54 +0000</pubDate>
      <link>https://dev.to/paras594/node-js-morgan-guide-431o</link>
      <guid>https://dev.to/paras594/node-js-morgan-guide-431o</guid>
      <description>&lt;p&gt;Any server or application needs some kind of logging system. It is common to skip logging in personal or practice project. But it is a must to have a fairly robust logging system in production ready servers and apps. &lt;/p&gt;

&lt;p&gt;Benefits of a logging system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs are used by product managers and UX designers for planning &amp;amp; design.&lt;/li&gt;
&lt;li&gt;It helps marketers track performance of various features related to advertising campaigns.&lt;/li&gt;
&lt;li&gt;It gives us the idea of how much traffic is the application getting.&lt;/li&gt;
&lt;li&gt;Track errors, attacks and unsuccessful requests in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting started with Morgan
&lt;/h2&gt;

&lt;p&gt;Morgan is a logging package for node.js. It can generate log files for all the traffic that comes to your server. It has some cool tricks to help us in both development and production. So let's get started. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Morgan&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;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;morgan &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Basic Morgan Usage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Adding morgan to middlewares in express is enough to get you started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;morgan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;morgan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// import morgan&lt;/span&gt;

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

&lt;span class="c1"&gt;// setup morgan&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;morgan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App listening on :3000&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;Above setup will start logging requests in console. You can see, I have specified &lt;code&gt;dev&lt;/code&gt; in morgan setup. There are many presets available in morgan and one them is &lt;code&gt;dev&lt;/code&gt;. Some other presets are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tiny&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;code&gt;short&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;common&lt;/code&gt; : Follows Apache like log format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Logging requests to file
&lt;/h2&gt;

&lt;p&gt;Now we will learn how to output logs to a file. Instead of creating simple logging to file, we will create rotating logs. Rotating logs are logs that covers a part of activity on the server in a file and then creates a new log file. This way we can keep track of past activities. We don't have to keep one single log file open for continuous logging. So, let's setup this.&lt;/p&gt;

&lt;p&gt;For rotating logs, we will install a package named &lt;code&gt;rotating-file-stream&lt;/code&gt;. It will help us automate log rotation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;rotating-file-stream &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Setup Morgan&lt;/strong&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;morgan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;morgan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// import morgan&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rfs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rotating-file-stream&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;span class="c1"&gt;// MORGAN SETUP&lt;/span&gt;
&lt;span class="c1"&gt;// create a log stream&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rfsStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;log.txt&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;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10M&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// rotate every 10 MegaBytes written&lt;/span&gt;
   &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// rotate daily&lt;/span&gt;
   &lt;span class="na"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gzip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// compress rotated files&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// add log stream to morgan to save logs in file&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;morgan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&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;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rfsStream&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="c1"&gt;// another logger to show logs in console as well&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;morgan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App listening on :3000&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;That was enough to setup our logging system but we can add environment variables to make it more intuitive to enable and disable logging to file&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding environment variables to our setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will need &lt;code&gt;dotenv&lt;/code&gt; package to load environment variables in nodejs from &lt;code&gt;.env&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now create a &lt;code&gt;.env&lt;/code&gt; file in the root directory of project and add the following variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOG_FILE=log.txt
LOG_FORMAT=common
LOG_SIZE=10M
LOG_INTERVAL=1d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's change our configuration to use these variables&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="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// load variables from .env file&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;morgan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;morgan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// import morgan&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rfs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rotating-file-stream&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;span class="c1"&gt;// MORGAN SETUP&lt;/span&gt;
&lt;span class="c1"&gt;// create a log stream&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rfsStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;log.txt&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;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_SIZE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10M&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_INTERVAL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;compress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gzip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// compress rotated files&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// if log file defined then use rfs stream else print to console&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;morgan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_FORMAT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&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;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_FILE&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;rfsStream&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="c1"&gt;// if log file is defined then also show logs in console&lt;/span&gt;
&lt;span class="c1"&gt;// else it will use the previous process.stdout to print to console&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;morgan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOG_FORMAT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App listening on :3000&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;With above configuration we can relax and let morgan handle the job of logging. Whenever an error occurs, visit the log file and you can track where things went wrong. &lt;/p&gt;

&lt;p&gt;I hope this article helped you understand why it important to have a good logging system and how to add one in express.&lt;/p&gt;

</description>
      <category>node</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Learn MongoDB: Working with Indexes</title>
      <dc:creator>Paras 🧙‍♂️</dc:creator>
      <pubDate>Tue, 02 Feb 2021 15:30:07 +0000</pubDate>
      <link>https://dev.to/paras594/learn-mongodb-working-with-indexes-36p9</link>
      <guid>https://dev.to/paras594/learn-mongodb-working-with-indexes-36p9</guid>
      <description>&lt;p&gt;In mongodb, we can create indexes on fields so that when we query data using that field, we can get results instantly. It is like accessing a value from an array using index. Without index, we have to look for the data in linear way, which is not optimal in large datasets. So, we will learn about indexes in this post.&lt;/p&gt;

&lt;p&gt;Let's begin !!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Table of Content&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is indexing ?&lt;/li&gt;
&lt;li&gt;How indexing works ?&lt;/li&gt;
&lt;li&gt;Working with Indexes&lt;/li&gt;
&lt;li&gt;Creating Index&lt;/li&gt;
&lt;li&gt;Get Indexes&lt;/li&gt;
&lt;li&gt;Check Your Index&lt;/li&gt;
&lt;li&gt;Drop Index&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Indexing is a way to optimize the performance of accessing data from database. It allows us to efficiently fetch data from our database without having to traverse it as a whole. You can think of it like arrays or maps where we use index or key to get our data without having to search for it in a linear way.&lt;/p&gt;

&lt;h2&gt;
  
  
  How indexing works ?
&lt;/h2&gt;

&lt;p&gt;Indexing, in background, keeps a table of key-value pair i.e. a table with two columns. First column has the key, which is actually the value that we want to search for in the table. For example: if we create an index on name field, then first column will have all the names in the database. While the second column keeps track of the pointers to the actual data. With the help of pointers, we fetch the actual data from our database.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search Key&lt;/th&gt;
&lt;th&gt;Database References (Values)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arthur&lt;/td&gt;
&lt;td&gt;reference_key_1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ash&lt;/td&gt;
&lt;td&gt;reference_key_2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;John&lt;/td&gt;
&lt;td&gt;reference_key_3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One good property of index table is keeping search keys in sorted order. In our case, search keys are stored in alphabetical order. This helps us find data much quickly (if you know binary search, then you know why sorting is helpful). &lt;/p&gt;

&lt;p&gt;Also, if you are confused about what are these reference keys, then in this example we can say that these are the primary keys (in mongodb "_id" keys). They refer to the user in our database. These keys are already indexed, and data can be retrieved quickly using these "id" keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with Indexes
&lt;/h2&gt;

&lt;p&gt;For working with indexes, we have a few cool methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;createIndex&lt;/li&gt;
&lt;li&gt;dropIndex&lt;/li&gt;
&lt;li&gt;getIndexes&lt;/li&gt;
&lt;li&gt;explain (to check how your queries are performing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before starting let's see a simple schema based on pokemon &lt;code&gt;trainers&lt;/code&gt;. We will add fields according to our needs.&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;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;age:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;pokemons:&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pikachu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"electric"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;level:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"charizard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;level:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"squirtle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"water"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;level:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&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="err"&gt;badges:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"boulder badge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cascade badge"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;exp:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;bagItems:&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="err"&gt;pokeballs:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;heals:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&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;h2&gt;
  
  
  Creating Index
&lt;/h2&gt;

&lt;p&gt;Let's create an index on name 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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// 1 ascending &amp;amp; -1 descending&lt;/span&gt;

&lt;span class="c1"&gt;// index a nested field&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;bagItems.pokeballs&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;h2&gt;
  
  
  Get Indexes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;// _id is the default index&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check your index
&lt;/h2&gt;

&lt;p&gt;We will use &lt;code&gt;explain&lt;/code&gt; method to check if our queries are using the index or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&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="c1"&gt;// a bit more specific&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&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;allPlansExecution&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;If you apply the &lt;code&gt;explain&lt;/code&gt; method, you will get a big object with so many details, which can be overwhelming. But we will focus on main fields.&lt;/p&gt;

&lt;p&gt;Main fields are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;inputStage:&lt;/strong&gt; In this key, our main field is &lt;code&gt;winningPlan&lt;/code&gt;. It can be &lt;code&gt;COLLSCAN&lt;/code&gt; (Full Collection Scan) or &lt;code&gt;IXSCAN&lt;/code&gt; (Index Scan)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;executionTimeMillis:&lt;/strong&gt; It shows the time taken by your query to get the data. This is important because we will use this field to compare different indexes and queries execution time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;totalDocsExamined:&lt;/strong&gt; This field shows how many docs mongo has to check before returning results. The lower the number, the better.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You can see there is input stage in explain result. This is first stage where mongo gets the keys and pointers from index table and then use those pointers to fetch actual docs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Drop Index
&lt;/h2&gt;

&lt;p&gt;Deleting index is also very easy. Just specify the object with that 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="c1"&gt;// let's drop our age index&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// you can also specify index "name" that you can get from "getIndexes" method&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trainers&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;age_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;You should know that these are just the basics. We have a lot to cover like text index, compound index, multi-key index, more about execution and plan rejection, etc. etc. So, we learn these things in next post !&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Post :&lt;/strong&gt; Coming soon...!! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prev Post :&lt;/strong&gt; &lt;a href="https://dev.to/paras594/learn-mongodb-delete-documents-4207"&gt;Delete Documents&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>tutorial</category>
      <category>database</category>
      <category>nosql</category>
    </item>
  </channel>
</rss>
