<?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: Shahid Shaikh</title>
    <description>The latest articles on DEV Community by Shahid Shaikh (@shaikhshahid).</description>
    <link>https://dev.to/shaikhshahid</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%2F473518%2Fe7fe924a-1b85-4ed7-b549-d5eed344103a.jpeg</url>
      <title>DEV Community: Shahid Shaikh</title>
      <link>https://dev.to/shaikhshahid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shaikhshahid"/>
    <language>en</language>
    <item>
      <title>Redistill - High Performance Redis Compatible Key Value Database</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Wed, 04 Feb 2026 08:36:23 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/redistill-high-performance-redis-compatible-key-value-database-5ga</link>
      <guid>https://dev.to/shaikhshahid/redistill-high-performance-redis-compatible-key-value-database-5ga</guid>
      <description>&lt;p&gt;Redis has always been one of my go-to KV databases. I strongly believe in — and advocate for — a memory-first, disk-later approach when designing high-throughput, low-latency systems. Redis is fast and durable, but I kept wondering: can we build something Redis-like that’s even faster?&lt;/p&gt;

&lt;p&gt;That curiosity pushed me to experiment deeply with Redis and the RESP protocol. Eventually, I decided to “distil” Redis — strip it down to the essentials and build a lighter version that supports only the commands I use most often (Strings and Hashes) — and see if we could push throughput and latency even further.&lt;/p&gt;

&lt;p&gt;Turns out, we did.&lt;/p&gt;

&lt;p&gt;I’m happy to announce that I’m working on an open-source project called Redistill — a distilled Redis. It’s written in Rust and based on benchmarks run on AWS c7i.16xlarge (Intel, 64 cores, 128GB RAM) using memtier_benchmark, I can confidently say this is the fastest single-instance, Redis-compatible database available today.&lt;/p&gt;

&lt;p&gt;Project link: &lt;a href="https://github.com/redistill-io/redistill" rel="noopener noreferrer"&gt;https://github.com/redistill-io/redistill&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%2Fd191di2acxnhxw5znx47.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%2Fd191di2acxnhxw5znx47.png" alt="Throughput Comparison" width="800" height="689"&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%2F9cxqqob1dwsg13apg6g0.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%2F9cxqqob1dwsg13apg6g0.png" alt="Latency Comparison" width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just the beginning. The project is barely 8 weeks old. I still need to figure out clustering and other production-ready features, but so far, as a single instance, this is ready to use ina production environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;The entire motivation behind the project was to build my own KV database that works faster than Redis and supports the commands I use frequently. It doesn't need to be versatile like Redis, but it does one thing best - the fastest KV database possible.&lt;/p&gt;

&lt;p&gt;I also wanted to learn Rust, and this was a good opportunity to revisit the fundamentals of system design and build a database from scratch (not entirely scratch, I use RESP protocol).&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Characteristics
&lt;/h2&gt;

&lt;p&gt;Redistill supports the RESP protocol, so there is no need for code changes on the client side. Your existing code, which works with Redis, will work with Redistill, assuming you use commands Redistill supports. &lt;/p&gt;

&lt;p&gt;Below are some key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-performance in-memory key-value database&lt;/li&gt;
&lt;li&gt;Redis protocol compatible (RESP) - works with all Redis clients&lt;/li&gt;
&lt;li&gt;9.07M operations/second - 4.5x faster than Redis, 1.7x faster than Dragonfly&lt;/li&gt;
&lt;li&gt;5x lower latency (p50: 0.48ms vs Redis 2.38ms)&lt;/li&gt;
&lt;li&gt;Multi-threaded architecture with lock-free reads&lt;/li&gt;
&lt;li&gt;Optional persistence - Snapshot support for warm restarts (disabled by default for max performance)&lt;/li&gt;
&lt;li&gt;Production-ready security and monitoring features&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why not all Redis commands?
&lt;/h2&gt;

&lt;p&gt;This was intentional.&lt;/p&gt;

&lt;p&gt;I wanted a KV database for my personal and work uses. I used String and Hash commands almost 90% of the time. So keeping it lightweight was the design and not a restriction. &lt;/p&gt;

&lt;p&gt;Will I add more commands in the future? Of course, this is a FOSS project, so I'll let contributors add the commands as they seem fit. &lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;High-Performance KV Database - Fastest in-memory key-value database available&lt;/li&gt;
&lt;li&gt;Maximum Single-Instance Performance - 4.5x faster than Redis, 1.7x faster than Dragonfly per instance&lt;/li&gt;
&lt;li&gt;Lower Latency - Sub-millisecond p50 latency (0.48ms)&lt;/li&gt;
&lt;li&gt;Cost Efficient - 50-83% infrastructure savings (fewer instances needed)&lt;/li&gt;
&lt;li&gt;Drop-in Compatible - Works with existing Redis clients&lt;/li&gt;
&lt;li&gt;Production Ready - TLS, authentication, monitoring, health checks&lt;/li&gt;
&lt;li&gt;Multi-threaded - Utilises all CPU cores efficiently&lt;/li&gt;
&lt;li&gt;Optional Persistence - Snapshot support for warm restarts when needed (disabled by default)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;We recommend using Docker to quickly spin up Redistill in your machine or server.&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="c"&gt;# Run with default settings&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; redistill &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 shahidontech/redistill:latest

&lt;span class="c"&gt;# Test it works&lt;/span&gt;
redis-cli ping
&lt;span class="c"&gt;# PONG&lt;/span&gt;

redis-cli &lt;span class="nb"&gt;set &lt;/span&gt;hello world
&lt;span class="c"&gt;# OK&lt;/span&gt;

redis-cli get hello
&lt;span class="c"&gt;# "world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also have other methods, such as Homebrew and building from source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Competitive Benchmark (c7i.16xlarge)&lt;br&gt;
Independent comparison on AWS c7i.16xlarge (Intel, 64 cores, 128GB RAM) using memtier_benchmark with production-like configuration:&lt;/p&gt;
&lt;h3&gt;
  
  
  Test Configuration:
&lt;/h3&gt;

&lt;p&gt;Duration: 60 seconds&lt;br&gt;
Threads: 8, Connections: 160 (20 per thread)&lt;br&gt;
Pipeline: 30, Data size: 256 bytes&lt;br&gt;
Workload: 1:1 SET: GET ratio&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Redistill&lt;/th&gt;
&lt;th&gt;Dragonfly&lt;/th&gt;
&lt;th&gt;Redis&lt;/th&gt;
&lt;th&gt;vs Redis&lt;/th&gt;
&lt;th&gt;vs Dragonfly&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;9.07M ops/s&lt;/td&gt;
&lt;td&gt;5.43M ops/s&lt;/td&gt;
&lt;td&gt;2.03M ops/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.5x&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bandwidth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.58 GB/s&lt;/td&gt;
&lt;td&gt;923 MB/s&lt;/td&gt;
&lt;td&gt;337 MB/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.7x&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Avg Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.524 ms&lt;/td&gt;
&lt;td&gt;0.877 ms&lt;/td&gt;
&lt;td&gt;2.000 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.8x faster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;p50 Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.479 ms&lt;/td&gt;
&lt;td&gt;0.807 ms&lt;/td&gt;
&lt;td&gt;2.383 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5.0x faster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.7x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;p99 Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.215 ms&lt;/td&gt;
&lt;td&gt;1.975 ms&lt;/td&gt;
&lt;td&gt;2.959 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.4x faster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.2x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;p99.9 Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.591 ms&lt;/td&gt;
&lt;td&gt;2.559 ms&lt;/td&gt;
&lt;td&gt;4.159 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.6x faster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.6x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Key Observations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Redistill processed 544M total operations (2.7x more than Dragonfly, 4.5x more than Redis)&lt;/li&gt;
&lt;li&gt;Consistent low latency across all percentiles&lt;/li&gt;
&lt;li&gt;No errors or connection issues across all systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;p&gt;Redistill is a high-performance key-value database perfect for applications requiring maximum speed and minimal latency.&lt;/p&gt;

&lt;p&gt;Perfect For&lt;br&gt;
Session Storage&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1M+ operations/second&lt;/li&gt;
&lt;li&gt;Sub-millisecond latency&lt;/li&gt;
&lt;li&gt;Automatic TTL expiration&lt;/li&gt;
&lt;li&gt;60% cost reduction vs alternatives&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;API Response Caching&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;95%+ cache hit rates&lt;/li&gt;
&lt;li&gt;50-150x faster than database queries&lt;/li&gt;
&lt;li&gt;Automatic memory management&lt;/li&gt;
&lt;li&gt;LRU eviction is built in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate Limiting&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Millions of counters&lt;/li&gt;
&lt;li&gt;TTL-based cleanup&lt;/li&gt;
&lt;li&gt;High write throughput&lt;/li&gt;
&lt;li&gt;Perfect for API gateways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-time Leaderboards&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast reads for rankings&lt;/li&gt;
&lt;li&gt;Periodic score updates&lt;/li&gt;
&lt;li&gt;Can rebuild from the database&lt;/li&gt;
&lt;li&gt;Sub-millisecond queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not Recommended For&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical persistent data (optional snapshots available, but not real-time durability)&lt;/li&gt;
&lt;li&gt;Financial or transactional data (use ACID-compliant database)&lt;/li&gt;
&lt;li&gt;Data that cannot be regenerated (use a database)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;The Redistill uses the RESP protocol to communicate, so any Redis client library should be able to connect to Redistill and communicate as they are communicating with Redis with the same commands.&lt;/p&gt;

&lt;p&gt;For example, in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Node.js:&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;Redis&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;ioredis&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;redis&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;Redis&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&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;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;Contributions are welcome! Please:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open an issue to discuss proposed changes&lt;/li&gt;
&lt;li&gt;Follow Rust coding conventions&lt;/li&gt;
&lt;li&gt;Include tests for new features&lt;/li&gt;
&lt;li&gt;Update relevant documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project link: &lt;a href="https://github.com/redistill-io/redistill" rel="noopener noreferrer"&gt;https://github.com/redistill-io/redistill&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>redis</category>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>10 ChatGPT Prompts to Boost Developer Productivity</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Fri, 10 May 2024 16:38:43 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/10-chatgpt-prompts-to-boost-developer-productivity-ia9</link>
      <guid>https://dev.to/shaikhshahid/10-chatgpt-prompts-to-boost-developer-productivity-ia9</guid>
      <description>&lt;p&gt;As developers and engineers, we constantly seek ways to streamline our workflows, increase productivity, and solve complex problems efficiently. With the advent of advanced language models like ChatGPT, we now have powerful tools to assist us in our daily tasks.&lt;/p&gt;

&lt;p&gt;By leveraging the capabilities of ChatGPT, we can generate prompts that enhance our productivity and creativity, making us more effective problem solvers and innovators.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore 10 ChatGPT prompts tailored specifically for developers and engineers to boost their productivity and streamline their workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Refactoring Suggestions
&lt;/h2&gt;

&lt;p&gt;Here is the sample prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I have a code that needs refactoring. Can you provide suggestions to improve its readability and efficiency? Here is the code: ”&lt;br&gt;
*&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use ChatGPT to generate recommendations for refactoring code snippets, such as identifying redundant lines, suggesting better variable names, or proposing alternative algorithms to optimize performance.&lt;/p&gt;

&lt;p&gt;Please refer to the screenshot below:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Suggest better code using ChatGPT prompts
&lt;/h2&gt;

&lt;p&gt;Here is the response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiegvjwwyvh6fjut434u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiegvjwwyvh6fjut434u.png" alt="ChatGPT Query" width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT response &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fq121y4roxph0hd1s59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fq121y4roxph0hd1s59.png" alt="ChatGPT response" width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Assistance:
&lt;/h2&gt;

&lt;p&gt;Here is the sample prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m encountering an error message [insert error message here] in my code. Can you help me troubleshoot and find a solution?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This prompt will help you troubleshoot bugs or issues in your code. Again, there may need a couple of iterations to really nail down the problems but this is a good starting prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Documentation Retrieval
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m working with the [insert API name] API. Can you provide me with relevant documentation or usage examples?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This is really helpful when we are working with new systems or platforms and instead of reading all the documentation, you can ask the ChatGPT to retrieve useful information for you in a summarized way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Pattern Recommendations
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m designing a new software component. Here is the requirement: [ Put your requirement here]. What design pattern would you recommend for implementing [insert functionality]?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This prompt requires a good level of detail but it can help you recommend some of the best design patterns you should use for your problem set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithm Optimization Techniques
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m implementing [insert algorithm name]. Are there any optimization techniques or best practices I should consider?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This is not only limited to algorithms but you can use some code as well. In short, this prompt will help you optimize the algorithm/code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Review Feedback
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’ve written a new feature. Can you review my code and provide feedback on potential improvements? Here is the code : [Insert code here]”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
ChatGPT can provide some really good feedback about your code. You may or may not implement all those feedbacks but it can certainly be a good starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library or Framework Recommendations
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m starting a new project. Can you recommend a suitable [insert programming language] library or framework for [insert functionality]?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
ChatGPT can suggest popular libraries, frameworks, and tools based on the programming language and desired functionality, enabling you to make informed technology choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Documentation Summaries
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I need a summary of the [insert technology or concept] technical documentation. Can you provide a concise overview?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This is my most used prompt, I summarize the technical documentation and read the gist, this has certainly improved my productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Snippet Generation
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I need a code snippet for [insert functionality or task]. Can you generate a sample code snippet?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
This is a good prompt to generate a starter code pack. But be sure not just to copy the code and use it, be cautious with the code generated by LLMs as they contain security flaws and bugs as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Planning and Task Prioritization
&lt;/h2&gt;

&lt;p&gt;Here is the prompt:&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;“I’m planning my project roadmap. Can you suggest a prioritized list of tasks based on [insert project requirements or constraints]?”&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
ChatGPT can analyze project requirements, dependencies, and deadlines to generate a prioritized task list, helping you effectively manage project timelines and deliverables.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
Incorporating ChatGPT prompts into your development workflow can significantly enhance productivity, creativity, and problem-solving capabilities. By leveraging ChatGPT’s natural language understanding and generation capabilities, developers and engineers can streamline tasks such as code refactoring, troubleshooting, documentation retrieval, and project planning. By integrating ChatGPT into your toolkit, you empower yourself to tackle challenges more effectively and unlock new levels of innovation in your projects.&lt;/p&gt;

&lt;p&gt;This article originally posted at &lt;a href="https://shaikhshahid.com/blog/10-chatgpt-prompts-to-boost-developer-productivity/79/"&gt;https://shaikhshahid.com/blog/10-chatgpt-prompts-to-boost-developer-productivity/79/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>generativeai</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Exploring Codium GitHub Pull Request AI Assistant</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Wed, 27 Dec 2023 08:58:25 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/exploring-codium-github-pull-request-ai-assistant-1i32</link>
      <guid>https://dev.to/shaikhshahid/exploring-codium-github-pull-request-ai-assistant-1i32</guid>
      <description>&lt;p&gt;I work in a software development and consulting firm and a large portion of my day is spent reviewing pull requests from different projects. Pull requests a.k.a merge requests are the contributions done by the engineers, generally covered by the unit tests. &lt;/p&gt;

&lt;p&gt;My job is to ensure the pull requests follow our standards and do the review of the code or delegate to one of the architects to review it if my plate is full or I am busy with some other work. &lt;/p&gt;

&lt;p&gt;Here are some of the standards that I make sure everyone is following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Jira ticket link is mentioned in the PR title.&lt;/li&gt;
&lt;li&gt;The ticket description is not vague or one-liners and explains the changes and how it is tested.&lt;/li&gt;
&lt;li&gt;Unit test coverage (more than 80%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And some more project-related details. Every developer in my team always cries over filling in all these details and they always say “Look at the code”. I  understand this frustration as I used to bash the same to my seniors. &lt;/p&gt;

&lt;p&gt;I use Github copilot and some of my team members also use the same. It’s a fantastic tool that provides real-time code suggestions and helps us write code/tests faster. &lt;/p&gt;

&lt;p&gt;GitHub announced copilot for PR and we were excited about it. While this is on the waiting list and should be available soon, I got the article suggestion on &lt;strong&gt;dev.to&lt;/strong&gt; platform about a similar tool, opened the article and was astonished to know that the team at Codium has already done this, and they did it better!&lt;/p&gt;

&lt;p&gt;After reading and using the Codium PR description for a day, I wanted to document and write a blog about it for fellow developers and engineers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Pull Requests Less Painful Using Codium PR AI Agent
&lt;/h2&gt;

&lt;p&gt;Codium AI and Github Copilot both use artificial intelligence to assist developers in writing better pull request descriptions and titles, detecting security flaws and much more. &lt;/p&gt;

&lt;p&gt;One of the key differences between them is that Codium provides open-source solutions that can be integrated into our infrastructure. This is a major advantage over Github because the cost of a subscription to Copilot is high when you have a team of say 20 developers.&lt;/p&gt;

&lt;p&gt;There are other key differences as well and they are the key factors why you should consider Codium like I did over GitHub PR tool. &lt;/p&gt;

&lt;p&gt;One major difference is that Codium supports all Git-based platforms. I have many clients who use self-hosted Gitlab and they just simply cannot use Copilot because it’s supported only on GitHub. This was one of the key reasons why we started researching such tools. &lt;/p&gt;

&lt;p&gt;The open-source version of the &lt;a href="https://github.com/Codium-ai/pr-agent#Quickstart"&gt;Codium PR agent&lt;/a&gt; is one of the best approaches to using Codium in the infrastructure maintained by the team.  We used the docker image to install this and it was easy as cake! There are other ways to install as well so you are not limited by options. &lt;/p&gt;

&lt;h2&gt;
  
  
  How PR Agent Works
&lt;/h2&gt;

&lt;p&gt;Here is the detailed diagram from the official Codium website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W9DaRJVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wyle2egxpz0yo6ez3qd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W9DaRJVC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wyle2egxpz0yo6ez3qd.png" alt="Image description" width="800" height="390"&gt;&lt;/a&gt;&lt;br&gt;
Once the PR agent is installed in Github or any supported Git-based software. You can invoke the PR agent by using different commands such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/review - Reviews the PR and provides you with gist information.&lt;/li&gt;
&lt;li&gt;/describe - generates a description of the PR.&lt;/li&gt;
&lt;li&gt;/ask ? - ask any question such as “suggest any fixes”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And more.&lt;/p&gt;

&lt;p&gt;The GitHub PR tool will provide a similar experience and we will know more about it once it’s live for everyone. I would rather recommend using Codium because of its seamless integration within a system and provides support to almost all programming languages. &lt;/p&gt;
&lt;h2&gt;
  
  
  Using PR Agent in Github
&lt;/h2&gt;

&lt;p&gt;Let’s try to use Codium’s PR agent in GitHub and see how it adds value to our workflow. I am going to use a public repo in my profile to show you how it works. For the demo, we are going to use the pre-described Codium PR Agent image in the GitHub actions. &lt;/p&gt;

&lt;p&gt;You can refer to the documentation &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/INSTALL.md#run-as-a-github-action"&gt;here&lt;/a&gt; as you follow the article. &lt;/p&gt;

&lt;p&gt;First thing, create a &lt;strong&gt;.github/workflow&lt;/strong&gt; folder in the code repository. Inside the &lt;strong&gt;workflow&lt;/strong&gt; folder, create a file named &lt;strong&gt;pr_agent.yml&lt;/strong&gt; and place this code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  pull_request:
  issue_comment:
jobs:
  pr_agent_job:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
      contents: write
    name: Run pr agent on every pull request, respond to user comments
    steps:
      - name: PR Agent action step
        id: pragent
        uses: Codium-ai/pr-agent@main
        env:
          OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need an openAI API key, you can obtain it by signing up here and creating an API key. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SvCq4uvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc1apl8r6f0ukn9bn1xh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SvCq4uvj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc1apl8r6f0ukn9bn1xh.png" alt="Image description" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, take the API key and open the &lt;strong&gt;Settings&lt;/strong&gt; page of your GitHub repository. Go to &lt;strong&gt;Secrets&lt;/strong&gt; and &lt;strong&gt;Variables -&amp;gt; Actions&lt;/strong&gt;. Here create a new repository access add the key name &lt;strong&gt;OPENAI_KEY&lt;/strong&gt; and place your openAI API key. &lt;/p&gt;

&lt;p&gt;There you go, now we can use the Codium PR agent. The Github token will be created automatically by Github so we don’t need to worry about it. &lt;/p&gt;

&lt;p&gt;Now go ahead and create a pull request in your repository. Once your pull request is created, the PR agent will automatically add a comment mentioning a bit of detail. Here is the screenshot for reference. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ai3c4G7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2f8q5k5sg887uhm4u5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ai3c4G7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2f8q5k5sg887uhm4u5k.png" alt="Image description" width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s see how the PR agent can provide us with more details. To add PR agent commands, we need to add a command with the commands in it. &lt;/p&gt;

&lt;p&gt;I am adding the first command as /describe and the PR agent will generate and add a comment to the pull request as an output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JP1CH2Sw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dgorhwsnipn0v72fhla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JP1CH2Sw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dgorhwsnipn0v72fhla.png" alt="Image description" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jug8fSqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/muilieswizbdcpu1i7x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jug8fSqa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/muilieswizbdcpu1i7x3.png" alt="Image description" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome!&lt;/p&gt;

&lt;p&gt;Now, let’s generate labels for this pull request. Add &lt;strong&gt;/generate_labels&lt;/strong&gt; to the comment box and let the PR agent do the magic. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_T1rsTZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxthpnvamiclujja4p1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_T1rsTZT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fxthpnvamiclujja4p1g.png" alt="Image description" width="714" height="1084"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PR agent automatically analyzed and added the label Tests to the pull request. &lt;/p&gt;

&lt;p&gt;Let’s try another command and try to generate the changelog. Add &lt;strong&gt;/update_changelog&lt;/strong&gt; and you should have a comment added as an output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jCxAxA4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juz6jd0awf7qmfk84ey6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jCxAxA4w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/juz6jd0awf7qmfk84ey6.png" alt="Image description" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go ahead and explore more commands and use the power of Codium’s PR agent to enhance your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;This is where it gets more interesting. Codium PR agent as I mentioned earlier is open source and can be used in any git-supported platform such as Gitlab, Github, etc. It’s free to use and you only need to configure your openAI API key. It’s way cheaper than GitHub for sure. &lt;/p&gt;

&lt;h2&gt;
  
  
  Data Privacy
&lt;/h2&gt;

&lt;p&gt;Codium doesn’t store any communication data. Since it’s linked with OpenAI, the communication between your PR instance and openAI is with you and not with Codium. &lt;/p&gt;

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

&lt;p&gt;AI solutions are one of the great productivity contribution elements in software development fields. We want to ensure that the majority of hours of developers are involved in writing good code and the rest is metadata work.  Assisting and automating the developer workflow will save so many hours and cost and the Codium PR tool is one of those tools which is a game changer. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>developers</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Building Email Spam Detection Model in Python</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Thu, 21 Sep 2023 08:21:30 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/building-email-spam-detection-model-in-python-2549</link>
      <guid>https://dev.to/shaikhshahid/building-email-spam-detection-model-in-python-2549</guid>
      <description>&lt;p&gt;I am pretty sure everyone who is reading this knows about email spam. This is a very general problem; almost all major email platforms have solved this problem to some extent. But, have you wondered how it actually works? In this article, we are going to explore the same and build and train a Machine Learning model that will detect incoming email and identify it as spam or ham.&lt;/p&gt;

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

&lt;p&gt;This is going to little a lengthy tutorial so be ready with your coffee and make sure the following software is already installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Jupyter Notebook&lt;/li&gt;
&lt;li&gt;Visual Studio Code or Editor of your choice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are quick links to the installation page of &lt;a href="https://www.python.org/downloads/"&gt;Python&lt;/a&gt; and &lt;a href="https://jupyter.org/install"&gt;Jupyter Notebook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You should also install the Anaconda package that contains the majority of the libraries we need for Machine learning in Python. Click &lt;a href="https://www.anaconda.com/download"&gt;here&lt;/a&gt; to go to the downloads page.&lt;/p&gt;

&lt;p&gt;I also assume that you know the basics of Machine learning and Python because I won't be digging too deep into basic concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Build and train a Machine learning model with good accuracy to detect emails as spam or ham (no spam). We should use standard libraries available for Machine learning model building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dataset
&lt;/h2&gt;

&lt;p&gt;To train any model, you need a pre-defined dataset that contains good and clean data. By clean I mean it should not have null values, ambiguous data or empty data. For this tutorial, I have identified a clean dataset and you can download it directly by clicking the link below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shaikhshahid.com/wp-content/uploads/2023/09/spam.csv"&gt;Spam Dataset&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Let's jump into the code. Open your Jupyter Notebook and import all the libraries we will need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import numpy as np
import pandas as pd
from sklearn.model_selection  import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, import the CSV you just downloaded as a pandas data frame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;emailData = pd.read_csv("spam.csv")
emailData.head(10)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should have the file data in your notebook similar to this.&lt;/p&gt;

&lt;p&gt;Analyze the data and ensure there are no null values using the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;emailData.shape
emailData.isnull().sum()
emailData.describe()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our target variable in the dataset is the Category and we should convert it into a numerical variable for the model. Here we will map it this way&lt;/p&gt;

&lt;p&gt;Spam -&amp;gt; 1&lt;/p&gt;

&lt;p&gt;Ham -&amp;gt; 0&lt;/p&gt;

&lt;p&gt;Here is the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;emailData['Spam'] = emailData.Category.map({"spam":1, "ham":0})
emailData.drop("Category",axis=1,inplace=True)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our data is clean and ready to be used in the model building.&lt;/p&gt;

&lt;p&gt;Now our target variable is Spam which will determine whether the e-mail is spam or ham. First, will define X and Y variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X = emailData.Message
y = emailData.Spam
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;X is our input which is email messages in the data file and y is our target variable.&lt;/p&gt;

&lt;p&gt;Next, we will split our data in a 70-30 split. 70% of the data will be used for training our model and 30% of it will be used for testing purposes. It's not a set practice and some engineers choose 75-25 split which is also fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=1,test_size=0.3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The random state ensures that every time we run the code it will produce the same test and train split.&lt;/p&gt;

&lt;p&gt;Now comes the important part, we need to convert the email and the words in those emails as tokens and we also need to avoid stop words to not create confusion. Let's create that using the CountVectorizer package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vect = CountVectorizer(stop_words='english')
vect.fit(X_train)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's transform them into a numerical format for the model to understand better.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X_train_transformed = vect.transform(X_train)
X_test_transformed = vect.transform(X_test)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's build a model. We will be building a multinominal Naive Bayes Model which is widely used for text-based prediction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mnb = MultinomialNB()
mnb.fit(X_train_transformed,y_train)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, that our model is instantiated, let's test it with our test data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y_pred = mnb.predict(X_test_transformed)

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

&lt;/div&gt;



&lt;p&gt;Let's check the accuracy score.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;metrics.accuracy_score(y_pred, y_test)

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

&lt;/div&gt;



&lt;p&gt;For me, it's coming around &lt;strong&gt;0.9856459330143541&lt;/strong&gt; i.e 98% accuracy.&lt;/p&gt;

&lt;p&gt;Testing the Model with Real Data&lt;/p&gt;

&lt;p&gt;Time to test our model with some real data. I copied the following e-mail from my Gmail Inbox to see how it detects spam and ham.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;emails=[
    'Sounds great! Are you home now?',
    'Will u meet ur dream partner soon? Is ur career off 2 a flyng start? 2 find out free, txt HORO followed by ur star sign, e. g. HORO ARIES',
    'Hello My Name is Gabriel Robert a top Bank Officer with Standard Bank of South Africa and I am in need of a reliable foreigner to carry out this important deal. An account was opened in my bank by one of my customers a Dutch National from Germany who made a fixed deposit of $11,100,000.00 (Eleven Million, One hundred Thousand United States Dollars) and never show up again and I later discovered that he died with his entire family members on a plane crash that occurred in Libya on the 12th of May 2010 which I can give you a link to that crash if you care. Since nobody is coming for this fund or knows about this fund I want to present a foreigner like you as next of kin to my late client so we can make the claim and you can contact me if you are interested so I can give you more detailed information about this transaction. For the sharing of the money will be shared in the ratio of 50% for me, 40% for you and 10% to cover our expenses after the deal. Now the total amount to be transferred is $12.2 million because of the interest the fund has accumulated for some recent time. Please keep this absolutely confidential and tell me if you are interested but I can assure you 100% risk free as I know how to go about it. Waiting for your urgent reply and call. Thanks.'
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the code to predict this with our model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;email_1 = vect.transform(emails)
mnb.predict(email_1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should give us the following output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;array([0, 1, 1])

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

&lt;/div&gt;



&lt;p&gt;Here 0 means ham and 1 means spam. So in my case, it is correct and detected the spam correctly. Do a test with your own e-mail data from your inbox and see how it's reacting to your data.&lt;/p&gt;

&lt;p&gt;This article was first published on &lt;a href="https://shaikhshahid.com/blog/email-spam-detection-model-python/118/"&gt;Shahid's personal blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>MySQL pagination</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Tue, 20 Jul 2021 15:33:46 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/mysql-pagination-18d7</link>
      <guid>https://dev.to/shaikhshahid/mysql-pagination-18d7</guid>
      <description>&lt;p&gt;MySQL is one of the most popular database software and most loved as well by software engineers. I have used MySQL in tons of projects and have complete confidence in this software. I am sure if you have a software engineering background, you must have come across MySQL.&lt;/p&gt;

&lt;p&gt;MySQL stores data in the database and table format and when the size of data grows it becomes a performance bottleneck to read all of the data. For few thousand records, it’s alright to run a SELECT * query and fetch all the records. It’s not recommended to do it for hundred thousand or million records.&lt;/p&gt;

&lt;p&gt;Let’s consider a very simple data record, a user table that contains all the information about users. To fetch the record, you run this query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns all the records, you can filter them by providing a WHERE clause but the MySQL engine needs to scan all of the records to find the match.&lt;/p&gt;

&lt;p&gt;To avoid this scenario, we use the pagination approach. In the pagination approach, we send back the information in pages or batches instead of the whole at once.&lt;/p&gt;

&lt;p&gt;For instance, we send 100 records per page and the application can request more data if requires by asking for the next page data.&lt;/p&gt;

&lt;p&gt;To achieve this in MySQL, we use the OFFSET and LIMIT clauses.&lt;/p&gt;

&lt;p&gt;The OFFSET clause lets you skip the records and the LIMIT clause lets you limit the record to a certain number.&lt;/p&gt;

&lt;p&gt;For example, if we want to read the 50 records per page. We run our query like this.&lt;/p&gt;

&lt;p&gt;For page 1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users OFFSET 0 LIMIT 50;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the next page i.e page 2, we tweak the query like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users OFFSET 50 LIMIT 50;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the next page i.e page 3, we tweak the query like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users OFFSET 150 LIMIT 50;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;This article was first published on &lt;a href="https://shaikhshahid.com/"&gt;Shahid's blog.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
    </item>
    <item>
      <title>Generating PDF Documents on the Fly Using Nodejs and Bull</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Mon, 19 Apr 2021 08:55:30 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/generating-pdf-documents-on-the-fly-using-nodejs-and-bull-2mn6</link>
      <guid>https://dev.to/shaikhshahid/generating-pdf-documents-on-the-fly-using-nodejs-and-bull-2mn6</guid>
      <description>&lt;p&gt;PDF documents are commonly used files in the majority of web applications. PDF documents are used in billing invoices, generating transaction reports, drafting the online agreement, etc. If you are building a SaaS then you might end up writing code or using a service to handle generating PDF documents on the fly as required by the system. &lt;/p&gt;

&lt;p&gt;In this tutorial, we are going to learn how to generate PDF documents on the fly using Node.js and the Bull queue system. &lt;/p&gt;

&lt;h2&gt;Generating PDF Documents using Nodejs and Bull&lt;/h2&gt;

&lt;p&gt;Bull is a Redis-backed queue system built for scalability. To use Bull, you must have Redis key-value database running in your system. You can download and run Redis by following the guide from the &lt;a href="https://redis.io/download" rel="noopener noreferrer"&gt;official download page of Redis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's begin with the project.&lt;/p&gt;

&lt;h3&gt;Create new project in Node&lt;/h3&gt;

&lt;p&gt;To create a new project in Node, create a new folder and name it as you like, open the terminal or command prompt and switch to the folder you created using the &lt;strong&gt;cd&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;Run this command to create a new Node project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init --y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will generate the boilerplate &lt;strong&gt;package.json&lt;/strong&gt; for your project.&lt;/p&gt;

&lt;p&gt;Run this command to install the dependencies required by the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save bull pdfkit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's code our project. Our codebase is divided into two important files, first is &lt;strong&gt;job.js&lt;/strong&gt; which is responsible for creating &lt;strong&gt;jobs&lt;/strong&gt; in the queue, and the second file is &lt;strong&gt;worker.js&lt;/strong&gt; responsible for fulfilling the jobs and creating PDF files. &lt;/p&gt;

&lt;p&gt;Let's check out each file and codebase first. Here is the job.js code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bull&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;bull&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;invoice&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;./invoice&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;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;bull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf-generation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startJob&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;invoiceData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;invoiceData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;singleInvoice&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="c1"&gt;// push data in queue&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Generate invoice &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;singleInvoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;singleInvoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this file, we are going through all the records present in the &lt;strong&gt;invoice.js&lt;/strong&gt; file. This is for sample record purposes, you can very well use the database records to the same.&lt;/p&gt;

&lt;p&gt;Here is the sample content of &lt;strong&gt;invoice.js&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello Shahid, You are charged $100 this month for services.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello Jack, You are charged $50 this month for services.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello Linda, You are charged $76 this month for services.&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;The codebase in &lt;strong&gt;job.js&lt;/strong&gt; retrieve and loop over this records and creates jobs in the queue for each record by having a delay of 1000ms. Let's check out our &lt;strong&gt;worker.js&lt;/strong&gt; code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bull&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;bull&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;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;bull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf-generation&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;pdfKit&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;pdfkit&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;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startProcess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// listen to the queue&lt;/span&gt;
    &lt;span class="c1"&gt;// start processing email&lt;/span&gt;
    &lt;span class="nx"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;job&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="c1"&gt;// on each request generate the pdf&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing Job with id &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;generatePdfInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generatePdfInvoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;pdfKit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createWriteStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/invoice/&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;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.pdf`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&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;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Generated PDF document`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;startProcess&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Worker running&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;We are using a node module called &lt;strong&gt;pdfkit&lt;/strong&gt; to generate our PDF documents. The function &lt;strong&gt;startProcess()&lt;/strong&gt; invokes the worker job and it listens to the queue and wait for any messages.&lt;/p&gt;

&lt;p&gt;Once it receives a message, we are calling &lt;strong&gt;generatePdfInvoice()&lt;/strong&gt; function with the information received in the message. In the &lt;strong&gt;generatePdfInvoice()&lt;/strong&gt; function, we are creating the PDF record by using the data coming from the queue and writing the PDF file in the &lt;strong&gt;invoice&lt;/strong&gt; folder. &lt;/p&gt;

&lt;p&gt;Let's run the code and see it's working.&lt;/p&gt;

&lt;p&gt;First, run the job.js code using the following command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then, run the worker.js file.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;Open the invoice folder and check the PDF files.&lt;/p&gt;

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

&lt;p&gt;We have successfully created the PDF file. This is a sample PDF file and you can add as many details as you want including images, tables, etc in your PDF files. &lt;/p&gt;

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

&lt;p&gt;We have studied how to use Node and queue systems such as Bull to design and build systems to generate PDF documents on the fly for business purposes.&lt;/p&gt;

&lt;p&gt;This article was first published on &lt;a href="https://codeforgeek.com/generating-pdf-documents-on-the-fly-using-nodejs-and-bull/" rel="noopener noreferrer"&gt;codeforgeek.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>redis</category>
    </item>
    <item>
      <title>What is Bitcoin and How does it work?</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Tue, 16 Mar 2021 12:04:58 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/what-is-bitcoin-and-how-does-it-work-3eha</link>
      <guid>https://dev.to/shaikhshahid/what-is-bitcoin-and-how-does-it-work-3eha</guid>
      <description>&lt;p&gt;Bitcoin is the world’s first peer-to-peer electronic cash system. Bitcoin offers anonymity, transparency, and no third-party dependent system to exchange value such as Money.&lt;/p&gt;

&lt;p&gt;Satoshi Nakamoto invented Bitcoin in 2009, and it’s been hailed as one of the most important inventions of the century.&lt;/p&gt;

&lt;p&gt;Bitcoin was invented to solve trust-based dependency in the current commerce system. We as people trust banks, governments, and federal reserves to safeguard money and provide a platform for the common man to trade and exchange using paper currency.&lt;/p&gt;

&lt;p&gt;Due to these trust-based models, the control of the economy is in the hands of a few people, who can use it for malicious purposes. I don’t want to go into detail about it because our article is not meant for bashing the banks and governments ;)&lt;/p&gt;

&lt;p&gt;However, there was no alternative, and you had to go to the bank to handle your financial needs. Then, Bitcoin arrived as a new and better alternative.&lt;/p&gt;

&lt;p&gt;To trade in Bitcoin, you don’t need any bank or government approval. You can send money to your peers using your computer or mobile. It’s as simple as that.&lt;/p&gt;

&lt;p&gt;In this article, we will learn in-depth about how Bitcoin works, how each transaction is formed and added to the block, and how it has done more than just solving our money problems.&lt;/p&gt;

&lt;p&gt;Note: I highly recommend our readers to print out the Bitcoin&lt;br&gt;
whitepaper written by Satoshi and give it a thorough read. You can download the paper from &lt;a href="https://bitcoin.org/bitcoin.pdf" rel="noopener"&gt;&lt;/a&gt;&lt;a href="https://bitcoin.org/bitcoin.pdf"&gt;https://bitcoin.org/bitcoin.pdf&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;What Is Bitcoin and How Does It Work?&lt;/h2&gt;

&lt;p&gt;Bitcoin is a peer-to-peer electronic payment system created in 2009 by Satoshi Nakamoto. Bitcoin allows us to send money to anyone in the world, without the need for a central authority such as banks to issue accounts or process payments.&lt;/p&gt;

&lt;p&gt;Bitcoin was created as a solution to the current financial system, where a marginal number of large corporations and banks control the financial world and the processing of transactions across the world.&lt;/p&gt;

&lt;p&gt;It centralizes the control of finance and commerce and forces people to trust the banks to act responsibly. And like Satoshi said in the P2P foundation.&lt;/p&gt;

&lt;blockquote&gt;"The central bank must be trusted not to debase the currency, but the history of fiat currencies is full of breaches of that trust"&lt;/blockquote&gt;

&lt;p&gt;Due to this trust issue, a major financial crisis affected the world at the end of 2007. This crisis inspired Satoshi to create &lt;strong&gt;Bitcoin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Bitcoin is a computer program. You can download it precompiled, or you can download the source code from &lt;a href="https://github.com/bitcoin/bitcoin" rel="noopener"&gt;Github&lt;/a&gt; and compile it&lt;br&gt;
yourself. Once you run the Bitcoin program on your computer, you become part of the network; you are a peer!&lt;/p&gt;

&lt;p&gt;Once your computer becomes a part of the network, the program&lt;br&gt;
will connect to other computers running the same program. Once&lt;br&gt;
connected, computers will start sharing a file and try to sync the files with each other; this file is nothing but a Blockchain. Once your computer is up to date with the Blockchain files, you can start submitting the transaction.&lt;/p&gt;

&lt;blockquote&gt;
It may raise a question: does everyone need to run the Bitcoin program to send/receive Bitcoin? Well, no. You can download a Bitcoin wallet and start making Bitcoin transactions. Those who wish to become a peer or miners in the network need to run the Bitcoin program
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HMmIEQtM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19174804/image_01_04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HMmIEQtM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19174804/image_01_04.png" alt="" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once your computer is synced with the latest copy of the Blockchain, you are good to go. You can now submit transactions, mine the blocks, read the Blockchain, and do whatever you wish to do.&lt;/p&gt;

&lt;p&gt;When a new transaction is submitted in the Blockchain, it is broadcast across the network. Every node then makes a copy of that transaction and adds it to their memory pool.&lt;/p&gt;

&lt;p&gt;In the Bitcoin network, at around &lt;strong&gt;~10 minutes&lt;/strong&gt; of the interval, one of the miners will mine a new block and broadcast it across the network. Every node will then update its Blockchain, and the network will be up to date:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8D_adSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19174927/image_01_05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8D_adSU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19174927/image_01_05.png" alt="" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This peer-to-peer nature of the system creates a trust-free, electronic cash system that runs with a solid consensus mechanism.&lt;/p&gt;

&lt;p&gt;Before we proceed ahead with the technical aspects of Bitcoin,&lt;br&gt;
let’s understand one of the key issues that Bitcoin solved—double-spending.&lt;/p&gt;

&lt;h2&gt;What is a Double Spending Issue?&lt;/h2&gt;

&lt;p&gt;Bitcoin is a peer-to-peer system, so what if two nodes submit the same transaction at the same time? How will the network with no central authority handle such a scenario? It is a serious and groundbreaking issue; let’s learn how Bitcoin solved it.&lt;/p&gt;

&lt;p&gt;Bitcoin solved this problem by introducing a memory pool. The&lt;br&gt;
memory pool is a buffer that every node has to maintain. The memory pool contains the transactions that are later written to the Blockchain.&lt;/p&gt;

&lt;p&gt;When a node submits a new block, it is broadcast throughout the&lt;br&gt;
network:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z_01PVTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19175813/image_01_06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z_01PVTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19175813/image_01_06.png" alt="" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a new block is submitted to the network, every node has to&lt;br&gt;
accept that as a  &lt;strong&gt;"correct" &lt;/strong&gt;transaction and remove any conflicting transaction from their memory pool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8H0OgNy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19175939/image_01_07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y8H0OgNy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/19175939/image_01_07.png" alt="" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, no chance of double spending can occur because it won’t persist in the network if it’s already been added to the block.&lt;/p&gt;

&lt;p&gt;This double-spending issue is groundbreaking and opens the way&lt;br&gt;
for many other projects such as Ripple cryptocurrency, which works with the current finance system but offers a solution to the double-spending.&lt;/p&gt;

&lt;p&gt;Now, let’s look over the technical aspects of Bitcoin.&lt;/p&gt;

&lt;h2&gt;Blocks&lt;/h2&gt;

&lt;p&gt;Block is the data structure that holds transactions in an immutable form. Bitcoin stores users’ transactions in the blocks, and later they form a chain to build a Blockchain network.&lt;/p&gt;

&lt;p&gt;As we discussed in the previous sections, the block is generated by the miner by the process of mining. The mining process requires a consensus algorithm to reach an agreement in the network.&lt;/p&gt;

&lt;p&gt;Block consists of the block header, which is used by the miner to generate the hash. Block header consists of the following:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;strong&gt;Version&lt;/strong&gt;: The version of the block&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Previous block hash&lt;/strong&gt;: Hash of the last identified block, thus forming a chain&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Merkle root&lt;/strong&gt;: Hash of all of the transactions in the block&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Time&lt;/strong&gt;: Timestamp&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Bits&lt;/strong&gt;: Hexadecimal version of the target value&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt;: Is a 32-bit random whole number that is adjusted by the miners, so that it becomes a valid number to be used to provide the hash of the block that should be less than the target hash.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two fields are self-explanatory, and we have already discussed them in the previous sections. Let’s learn about the Merkle tree.&lt;/p&gt;

&lt;h3&gt;Merkle Tree&lt;/h3&gt;

&lt;p&gt;Merkle tree is the data structure in which every leaf node is labeled with the cryptographic hash of the data, and every non-leaf node is labeled with the hash of its child nodes, forming a tree to the root with one hash value.&lt;/p&gt;

&lt;p&gt;As you can see in the following image, &lt;strong&gt;hash 0-0&lt;/strong&gt; and &lt;strong&gt;hash 0-1&lt;/strong&gt; is the hash value of data block L1 and L2. Later, &lt;strong&gt;Hash 0-0&lt;/strong&gt; and &lt;strong&gt;0-1&lt;/strong&gt; will be hashed together to form &lt;strong&gt;Hash 0&lt;/strong&gt; and so on until we reach a root hash:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EPLZHexj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23131207/image_01_08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EPLZHexj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23131207/image_01_08.png" alt="" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using a Merkle tree, we can generate a hash of a long series of data in a compact and secure format:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8n0qLpW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23131639/merkle-root.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8n0qLpW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23131639/merkle-root.png" alt="" width="788" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown in the preceding screenshot, the Merkle root contains transactions that are hashed together in a way the binary tree is formed.&lt;/p&gt;

&lt;p&gt;Merkle tree is formed by hashing the transaction IDs in a pair. Transaction IDs are used if needed, and we can perform a recheck using the transaction ID in a tree.&lt;/p&gt;

&lt;p&gt;To generate a Merkle tree, we take a pair of transaction IDs (TXID) and hash them twice using the SHA256 algorithm. The resulting hash is then hashed with another hashed pair twice to generate a single hash. This goes on till we generate a root hash.&lt;/p&gt;

&lt;p&gt;Merkle trees are best suited for applications such as Bitcoin, where the size of the data matters. Due to the use of the Merkle tree, the block size is retained to 1Mb max in Bitcoin.&lt;/p&gt;

&lt;blockquote&gt;Learn in-depth about the Merkle trees; it’s one of the most frequently asked questions on Facebook, Amazon, Apple, Netflix, Google (FAANG) companies. Start from &lt;a href="http://www.mit.edu/~rio/merkle.pdf" rel="noopener"&gt;here&lt;/a&gt;.&lt;/blockquote&gt;

&lt;p&gt;Let’s learn about the next field in the block header—Bits.&lt;/p&gt;

&lt;h3&gt;Bits&lt;/h3&gt;

&lt;p&gt;Bits is the field in the block header that stores the target value in the compact. Target is the value that is required for the miner to generate the block hash that is less than the target. We studied it in the Blockchain core concepts section.&lt;/p&gt;

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

&lt;p&gt;Here’s what a target value looks like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0x00000000000000000696f4000000000000000000000000000000000000000000&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Storing such long values will require size, and mind you, the target will keep changing in the future.&lt;/p&gt;

&lt;p&gt;To solve this, the target is compacted, and it looks like this in the block header field:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0x180696f4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s easy to store and takes less size.&lt;/p&gt;

&lt;p&gt;Here’s how to decode a bit. It’s divided into two parts. The first two bits after 0x represent the number of 0s in the target value, and the remaining values are appended after 0. The rest of the field is then filled with 0s till it reaches 48 bit.&lt;/p&gt;

&lt;p&gt;So, 0x180696f4 value can be written as:&lt;/p&gt;

&lt;p&gt;0x----18 times zero---0696f4---rest zeros----&lt;/p&gt;

&lt;p&gt;This way, we can decode the bits in the actual target value.&lt;/p&gt;

&lt;p&gt;In the next section, we’ll look at the field, the miner used to generate the hash of the block that is lower than the target value.&lt;/p&gt;

&lt;h3&gt;Nonce&lt;/h3&gt;

&lt;p&gt;The Nonce is the field in the block header that is used by the miner to generate a hash. Bitcoin uses proof of work consensus algorithms. In proof of work, Miner has to generate a hash that is lower than the target value decided by the network.&lt;/p&gt;

&lt;p&gt;Target value starts with several 0s, and it’s really difficult to get such a hash using the SHA256 algorithm on a random basis. So, Nonce comes into the picture, Miner uses the Nonce field to generate a hash, and if it is not lower than the target value, Miner increments the Nonce and tries again.&lt;/p&gt;

&lt;p&gt;When the lucky number or Nonce is found, a hash is generated. Miner announces the block in the network, and every other node verifies and makes a copy of it in their Blockchain.&lt;/p&gt;

&lt;p&gt;So, Nonce plays a crucial role in Bitcoin mining.&lt;/p&gt;

&lt;p&gt;We have studied the block and important block header fields, so let’s move ahead and learn about Bitcoin transactions.&lt;/p&gt;

&lt;h2&gt;Transactions&lt;/h2&gt;

&lt;p&gt;When someone tries to transfer Bitcoin from one account to another, a new transaction is formed and added to the block by the miner.&lt;/p&gt;

&lt;p&gt;The transaction contains data that is required for proper Bitcoin transfer. Transaction data consists of the amount that the user wants to send, account information such as from and to addresses, transaction information required for the network such as transaction Ids, and so on.&lt;/p&gt;

&lt;p&gt;Transaction in Bitcoin contains the following information:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;The transaction ID is also referred widely as TXID&lt;/li&gt;
    &lt;li&gt;Transaction data such as INPUT, OUTPUT, and so on&lt;/li&gt;
    &lt;li&gt;Fees&lt;/li&gt;
    &lt;li&gt;Weight&lt;/li&gt;
    &lt;li&gt;UTXO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s learn about each one of them in brief.&lt;/p&gt;

&lt;h3&gt;TXID&lt;/h3&gt;

&lt;p&gt;TXID is a 32 bytes hexadecimal number that is referred to as transaction ID and used to identify the transaction in Bitcoin.&lt;/p&gt;

&lt;p&gt;TXID is generated by hashing the transaction data twice using the SHA256 hashing algorithm.&lt;/p&gt;

&lt;p&gt;Satoshi Nakamoto sent the first-ever Bitcoin transaction to Hal Finney, and the ID of the transaction is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can still view this transaction in the Blockchain explorer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7vQx5wyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23132838/screenshot-www.blockchain.com-2021.02.23-13_28_20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7vQx5wyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23132838/screenshot-www.blockchain.com-2021.02.23-13_28_20.png" alt="" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s look over the transaction data required to form the transaction payload.&lt;/p&gt;

&lt;h3&gt;Transaction Data&lt;/h3&gt;

&lt;p&gt;Transaction data contains the information required to form INPUT and OUTPUT. Now, what are they? Well, in Bitcoin, when you send someone a few coins, you unlock a few outputs that are required and lock them again with the keys of the receiver so that only they can lock it.&lt;/p&gt;

&lt;p&gt;Sounds confusing? Stay with me.&lt;/p&gt;

&lt;p&gt;Let’s take an example:&lt;/p&gt;

&lt;p&gt;Imagine you have 5 Bitcoins, and you want to send 3 bitcoins to your friend. Here, 5 Bitcoins you hold is your OUTPUT, and it is split into two OUTPUT. One worth 3 Bitcoins and another worth 2 Bitcoins. The first OUTPUT will then be locked with the receiver keys so that they can unlock it. The second OUTPUT is your money, so it is again locked with your credentials for future uses.&lt;/p&gt;

&lt;p&gt;In a nutshell, when a new transaction is formed, the whole amount is included in the &lt;strong&gt;transaction payload&lt;/strong&gt;. It’s just whatever is left is being sent back to you as an OUTPUT.&lt;/p&gt;

&lt;p&gt;So, this approach of graph-based INPUT and OUTPUT structure provides a history of ownership of Bitcoin.&lt;/p&gt;

&lt;h3&gt;Fees&lt;/h3&gt;

&lt;p&gt;Every transaction in Bitcoin pays some amount of money in the form of Bitcoin to the Miner. The remainder of the transaction output is also associated with the fees and paid to the miner for the work they do.&lt;/p&gt;

&lt;p&gt;Generally, by adding lucrative fees, there is a high chance that a miner will pick your transaction from the memory pool to add into the next block. However, this is completely optional. If you don’t pay the fee at the moment, it may take some time, but your transaction will be mined by some miners scattered across the world.&lt;/p&gt;

&lt;p&gt;Here is the fee associated with the transaction. You can also check the miner award, which is 6.25 Bitcoin at the time of writing this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5IsYsR9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23133755/screenshot-www.blockchain.com-2021.02.23-13_35_36.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5IsYsR9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://image.codeforgeek.com/wp-content/uploads/2021/02/23133755/screenshot-www.blockchain.com-2021.02.23-13_35_36.jpg" alt="" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
The remainder of the transaction is also paid to the Miner as a fee. Suppose you want to pay someone 5 Bitcoin, and you have around 10 Bitcoin in your wallet, if you don’t claim the remaining 5 Bitcoin in the OUTPUT section of the transaction, it will be paid to the miner. It’s not refundable because, well, Blockchain is immutable! So, double-check before forming a transaction payload programmatically.
&lt;/blockquote&gt;

&lt;h3&gt;Weight&lt;/h3&gt;

&lt;p&gt;As the name suggests, it refers to the size of the transaction, that is, its weight. After the introduction of weight, the transaction payload is formed by putting the validation part at the end of the payload rather than with each INPUT, as we did earlier.&lt;/p&gt;

&lt;h3&gt;UTXO&lt;/h3&gt;

&lt;p&gt;It’s a short version of Unspent Transaction Output. When a new transaction is formed and new OUTPUT is generated, the one which is spent or sent to other users cannot be spent again. However, the OUTPUTs left or not spent can be used in future transactions.&lt;/p&gt;

&lt;p&gt;These unspent outputs are called UTXOs.&lt;/p&gt;

&lt;p&gt;UTXO is used to calculate the balance of a particular user and verify whether they have the amount to spend. UTXOs are a key part of forming new transactions and preventing double-spending.&lt;/p&gt;

&lt;p&gt;These are the key factors that are involved in the Bitcoin transaction.&lt;/p&gt;

&lt;p&gt;I hope you understood the concepts and the reasoning behind the technical changes done to make Bitcoin and Blockchain what they are now. Let's learn and understand another important and key technical aspect of Bitcoin - Cryptography.&lt;/p&gt;

&lt;h2&gt;Addresses and Keys&lt;/h2&gt;

&lt;p&gt;In order to send and receive Bitcoins, you need an address and to be specific a secure address. Bitcoin uses pair of public and private keys. The public and private keys play a crucial role in making a Bitcoin transaction secure and anonymous. The private key is generated by using a long random number and then converted to hexadecimal format. The public key is derived by using the private key. &lt;/p&gt;

&lt;p&gt;The compressed version of a public key is also known as an &lt;strong&gt;address&lt;/strong&gt; and you can share this with anyone publicly. Anyone around the globe can send you Bitcoin to your address. In order to send Bitcoin to other people, you need their public key and your private key. Your private key is a secret key and you must never share it with anyone. Each Bitcoin transaction is signed with the sender's private key along with the receiver's public key. &lt;/p&gt;

&lt;p&gt;For example, take a look at the private and public key pair shown below:&lt;/p&gt;

&lt;p&gt;Private key: &lt;strong&gt;ef235aacf90d9f4aadd8c92e4b2562e1d9eb97f0df9ba3b508258739cb013db2&lt;/strong&gt;&lt;br&gt;
Public key: &lt;strong&gt;02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737&lt;/strong&gt;&lt;br&gt;
Address: &lt;strong&gt;1EUXSxuUVy2PC5enGXR1a3yxbEjNWMHuem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no way to generate the same private key again and there is no way to re-generate the private key from the public key. This makes the private key a crucial part of the system. If you lose your private key, you lose your Bitcoins.&lt;/p&gt;

&lt;blockquote&gt;
This article is referred from the Book called &lt;a href="https://www.amazon.in/Building-Decentralized-Blockchain-Applications-Foundation-ebook/dp/B08V4TXSLW/ref=sr_1_1?crid=4XZBV9IXGBCY&amp;amp;dchild=1&amp;amp;keywords=decentralized+application&amp;amp;qid=1613559765&amp;amp;sprefix=decentralized+appl%2Caps%2C278&amp;amp;sr=8-1" rel="noopener"&gt;Building decentralized blockchain applications&lt;/a&gt;.Consider a purchase if you like our content. (PS: I am author of this book)
&lt;/blockquote&gt;

</description>
      <category>blockchain</category>
      <category>bitcoin</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Awesome Node.js Tools, Libraries and Resources</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Thu, 31 Dec 2020 13:18:03 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/awesome-node-js-tools-libraries-and-resources-26jg</link>
      <guid>https://dev.to/shaikhshahid/awesome-node-js-tools-libraries-and-resources-26jg</guid>
      <description>&lt;p&gt;Node.js is equipped with a rich ecosystem of tools, libraries, and frameworks to help developers build their application faster, safer, and follow the standard industry guidelines on software development. &lt;/p&gt;

&lt;p&gt;While there are hundreds of thousands of packages registered in the official node package manager repository, we have shortlisted a few based on the reputation and usability for a day to day software development. &lt;/p&gt;

&lt;p&gt;Let's jump in directly and check out some of the awesome Node.js tools, libraries, and frameworks. If you are new to Node, you can read our &lt;a href="https://codeforgeek.com/node-js-tutorial-step-by-step/" rel="noopener noreferrer"&gt;entry-level complete Node.js tutorial&lt;/a&gt; for beginners to get started.&lt;/p&gt;

&lt;h2&gt;Web frameworks&lt;/h2&gt;

&lt;p&gt;Here are some of the popular and widely used web frameworks available in the Node.js ecosystem.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; - A complete web application framework to develop various types of web applications such as Web server, API server,etc. We built this site on top of &lt;a href="https://codeforgeek.com/express-nodejs-tutorial/" rel="noopener noreferrer"&gt;Express framework&lt;/a&gt; and this article is served by an &lt;a href="https://codeforgeek.com/expressjs-router-tutorial/" rel="noopener noreferrer"&gt;Express router&lt;/a&gt; :) &lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/koajs/koa" rel="noopener noreferrer"&gt;Koa&lt;/a&gt; - A expressive framework designed by the team behind Express. Koa aims to provide enjoyable experience to developers while building a web application.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/hapijs/hapi" rel="noopener noreferrer"&gt;Hapi&lt;/a&gt; - a simple and secure framework to build web applications.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://sailsjs.com/" rel="noopener noreferrer"&gt;Sails.js&lt;/a&gt; - MVC (Model - view - controller) framework for Node.js.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/fastify/fastify" rel="noopener noreferrer"&gt;Fastify&lt;/a&gt; - Fastify is a web framework entirely focused on speed. It is one of the fastest framework in the Node.js ecosystem. &lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/senecajs/seneca" rel="noopener noreferrer"&gt;Seneca&lt;/a&gt; - It's a tool to write &lt;a href="https://codeforgeek.com/microservices-nodejs/" rel="noopener noreferrer"&gt;microservices&lt;/a&gt; based application in Node.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://moleculer.services/" rel="noopener noreferrer"&gt;Molecular&lt;/a&gt; - A mature, fast and powerful microservices framework for Node.js.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/adonisjs/" rel="noopener noreferrer"&gt;AdoniJS&lt;/a&gt; - is a framework to write micro-services easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;HTTP and Networking Stuff&lt;/h2&gt;

&lt;p&gt;Node.js is widely used in building networking applications. There will come a scenario where you as a developer asked to integrate third-party APIs such as payment API, invoice API, etc. To handle these tasks, you can use the libraries mention below.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/mzabriskie/axios" rel="noopener noreferrer"&gt;Axios&lt;/a&gt; - A widely used HTTP client for Node as well as the browser.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/sindresorhus/got" rel="noopener noreferrer"&gt;got&lt;/a&gt; - A simple and lightweight interface to make HTTP calls.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/http-party/node-http-proxy" rel="noopener noreferrer"&gt;HTTP proxy&lt;/a&gt; - a very useful tool to build a proxy server effortlessly especially in a microservice architecture.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/micromata/http-fake-backend" rel="noopener noreferrer"&gt;HTTP fake backend&lt;/a&gt; - a huge time saver tool. Allows you to create a fake backend server for the test and demo apps.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/kevva/download" rel="noopener noreferrer"&gt;download&lt;/a&gt; - utility to download files from a URL and save it in file system.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/bevry/getmac" rel="noopener noreferrer"&gt;getmac&lt;/a&gt; - get the MAC address of your computer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Database drivers and ODM/ORM&lt;/h2&gt;

&lt;p&gt;There is really no need to mention how important the database is for your application. Node.js can be integrated with almost every popular database.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/mysqljs/mysql" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt; - A pure JavaScript based driver to integrate with MySQL database. We have written a detailed tutorial about &lt;a href="https://codeforgeek.com/nodejs-mysql-tutorial/" rel="noopener noreferrer"&gt;Node.js and MySQL&lt;/a&gt;.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/mongodb/node-mongodb-native" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt; - A MongoDB database driver. Refer &lt;a href="https://codeforgeek.com/node-mongodb-tutorial/" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt; to learn how to use this driver to connect to MongoDB.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/Automattic/mongoose" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt; - A MongoDB object data model i.e ODM. &lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/brianc/node-postgres" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; - A database client for PostgreSQL database.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://www.npmjs.com/package/redis" rel="noopener noreferrer"&gt;Redis&lt;/a&gt; - A client for redis key value database.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/Level/levelup" rel="noopener noreferrer"&gt;LevelUP&lt;/a&gt; - A levelDB database.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/couchbase/couchnode" rel="noopener noreferrer"&gt;Couchbase&lt;/a&gt; - A client for a couchbase database.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/balderdashy/waterline" rel="noopener noreferrer"&gt;Waterline&lt;/a&gt; - A database agnostic that can interact with one or more database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Logging&lt;/h2&gt;

&lt;p&gt;Logging is an essential part of any web application. Node.js has some of the best logging library available. I personally uses winston a lot in my projects. It has rich set of plugins to extend the logging feature as per the requirenments.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/winstonjs/winston" rel="noopener noreferrer"&gt;winston&lt;/a&gt; - Asynchronous multi-transport logging library.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/pinojs/pino" rel="noopener noreferrer"&gt;pino&lt;/a&gt; - Fast logging library.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/guigrpa/storyboard" rel="noopener noreferrer"&gt;storyboard&lt;/a&gt; - a real time and colorful log.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Documentation&lt;/h2&gt;

&lt;p&gt;The only thing which almost every developer hate is creating a documentation. I know, I do too. But, it's an important thing to create a well written documentation as you write your beautiful code.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/jsdoc3/jsdoc" rel="noopener noreferrer"&gt;JSDoc&lt;/a&gt; - API documentation generator similar to JavaDoc.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/documentationjs/documentation" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; - library with modern JavaScript support.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/esdoc/esdoc" rel="noopener noreferrer"&gt;ESDoc&lt;/a&gt; - documentation generator with ES2015 support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Control flow&lt;/h2&gt;

&lt;p&gt;Node.js is asynchrnous in nature and it's little different than what we used to in high level languages such as Java, C++,etc. We can leverage libraries mentioned below to make our life little bit easier while writing Node.js application.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/caolan/async" rel="noopener noreferrer"&gt;async&lt;/a&gt; - a popular library to write asynchronous code in JavaScript using callbacks.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/petkaantonov/bluebird" rel="noopener noreferrer"&gt;Bluebird&lt;/a&gt; - a library to handle and write asynchronous code using promises.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Streams&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/sindresorhus/get-stream" rel="noopener noreferrer"&gt;get-stream&lt;/a&gt; - library to get a stream as a buffer or string.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/feross/multistream" rel="noopener noreferrer"&gt;multistream&lt;/a&gt; - combine multiple steams into a single stream.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/sindresorhus/into-stream" rel="noopener noreferrer"&gt;into-stream&lt;/a&gt; - convert existing buffer, array, string into a stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Real time&lt;/h2&gt;

&lt;p&gt;Node.js can be used to build a real time systems. I have used these library in some of the projects and they are pretty good.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/socketio/socket.io" rel="noopener noreferrer"&gt;Socket.io &lt;/a&gt;- A really useful library to develop real time web application.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/uWebSockets/uWebSockets" rel="noopener noreferrer"&gt;uWebSockets&lt;/a&gt; - A library that support event based real time features.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/deepstreamIO/deepstream.io-client-js" rel="noopener noreferrer"&gt;deepstream.io&lt;/a&gt; - A scalable real time framework to develop advanced application like games,etc.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/mqttjs/MQTT.js" rel="noopener noreferrer"&gt;MQTT&lt;/a&gt; - A pubsub library to develop applications with lightweight communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Authentication and Authorization&lt;/h2&gt;

&lt;p&gt;When you are building any web application, the most common part is going to be user authentication. You don't need to develop the modules again, Node.js libraries will cover it for you. The libraries listed below are tried and test library in thousands of projects.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/jaredhanson/passport" rel="noopener noreferrer"&gt;Passport&lt;/a&gt; - A widely used authentication library that support wide range of SSO.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/simov/grant" rel="noopener noreferrer"&gt;Grant&lt;/a&gt; - A middleware for web frameworks such as Express, koa, and Hapi.&lt;/li&gt;
    &lt;li&gt;
&lt;a href="https://github.com/casbin/node-casbin" rel="noopener noreferrer"&gt;node-casbin&lt;/a&gt; - Authorization library with ACL, RBAC and ABAC access control support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Email&lt;/h2&gt;

&lt;p&gt;You can use the libraries mentioned below to send an email from your application. &lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/andris9/Nodemailer" rel="noopener noreferrer"&gt;Nodemailer&lt;/a&gt; - A popular and widely used library to send emails.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/eleith/emailjs" rel="noopener noreferrer"&gt;emailjs&lt;/a&gt; - A simple and useful library to send text/html emails with attachment.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/mjmlio/mjml" rel="noopener noreferrer"&gt;MJML&lt;/a&gt; - Markup based to create responsive emails.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;Job Queues and Message queues&lt;/h2&gt;

&lt;p&gt;Job quues and message queues allows you to develop complex applications and schedule your job based on the requirenment. &lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/OptimalBits/bull" rel="noopener noreferrer"&gt;bull&lt;/a&gt; - extensible job and message queue. We use bull in Codeforgeek.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/rschmukler/agenda" rel="noopener noreferrer"&gt;agenda&lt;/a&gt; - Job scheduler using mongodb as a backend.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/taskrabbit/node-resque" rel="noopener noreferrer"&gt;node-resque&lt;/a&gt; - Job queue based on Redis.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/smrchy/rsmq" rel="noopener noreferrer"&gt;rsmq&lt;/a&gt; - Message queue based on Redis.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/bbc/sqs-consumer" rel="noopener noreferrer"&gt;sqs-consumer&lt;/a&gt; - library to handle amazon simple queue service in your application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Process Management&lt;/h2&gt;

&lt;p&gt;Node.js as a process is tricky to manage. Thanks to the libraries mentioned below especially PM2, managing a Node process is piece of cake.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/Unitech/pm2" rel="noopener noreferrer"&gt;PM2&lt;/a&gt; - a popular and widely used process manager for Node. We use PM2 in codeforgeek.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/remy/nodemon" rel="noopener noreferrer"&gt;nodemon&lt;/a&gt; - monitor changes in your file and restart the server on change detection.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/petruisfan/node-supervisor" rel="noopener noreferrer"&gt;supervisor&lt;/a&gt; - process manager which restarts the server upon crash.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Static Site Generator&lt;/h2&gt;

&lt;p&gt;Static sites are pretty popular now a days. With the adoption of gatsby and Netlify, things are moving towards the right direction. You can use the libraries mentioned below to create the static site using Node.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/jnordberg/wintersmith" rel="noopener noreferrer"&gt;Wintersmith&lt;/a&gt; - Multi-platform static site generator.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/assemble/assemble/" rel="noopener noreferrer"&gt;Assemble&lt;/a&gt; - Static site generator with a grunt extension.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/docpad/docpad" rel="noopener noreferrer"&gt;DocPad&lt;/a&gt; - static site generator with wide range of plugin ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Content Management System&lt;/h2&gt;

&lt;p&gt;Node.js has been used to develop some of the best CMS such as Ghost. You can any libraries and platforms mentioned below to create your CMS and manage your content.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/TryGhost/Ghost" rel="noopener noreferrer"&gt;Ghost&lt;/a&gt; - widely popular blogging and content management framework and platform.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/hexojs/hexo" rel="noopener noreferrer"&gt;Hexo&lt;/a&gt; - Simple yet powerful blogging framework.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/NodeBB/NodeBB" rel="noopener noreferrer"&gt;nodeBB&lt;/a&gt; - forum platform in Node.js.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/keystonejs/keystone" rel="noopener noreferrer"&gt;KeystoneJS&lt;/a&gt; - content management system built on Express and MongoDB.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/strapi/strapi" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; - Headless content management system to build API's.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://buttercms.com/docs/api-client/nodejs" rel="noopener noreferrer"&gt;ButterCMS&lt;/a&gt; - Headless content management system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Hardware&lt;/h2&gt;

&lt;p&gt;You can use Node in hardware devices as well. I have personally used Node in raspberryPI and it works great. You can use libraries mentioned below to build a DIY hardware projects.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/rwaldron/johnny-five" rel="noopener noreferrer"&gt;Johnny-Five&lt;/a&gt; - The JavaScript Robotics Programming Framework.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/voodootikigod/node-serialport" rel="noopener noreferrer"&gt;Node Serialport&lt;/a&gt; - Access serial port with Node. Works on cross-platform.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/nonolith/node-usb" rel="noopener noreferrer"&gt;USB&lt;/a&gt; - Node library for communicating with USB devices.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/fivdi/onoff" rel="noopener noreferrer"&gt;onoff&lt;/a&gt; - Supports RaspberryPI communication.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/infusion/GPS.js" rel="noopener noreferrer"&gt;GPS&lt;/a&gt; - Library to handle GPS receiver communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Miscellaneous&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;a href="https://github.com/atom/electron" rel="noopener noreferrer"&gt;Electron&lt;/a&gt; - Build a cross-platform desktop application using Node and JavaScript.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/peterbraden/node-opencv" rel="noopener noreferrer"&gt;OpenCV&lt;/a&gt; - Binding for OpenCV computer vision library.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/indexzero/nconf" rel="noopener noreferrer"&gt;nconf&lt;/a&gt; - Nodejs configuration file management.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/cheeriojs/cheerio" rel="noopener noreferrer"&gt;Cheerio&lt;/a&gt; - HTML DOM parser for Node and JavaScript.&lt;/li&gt;

    &lt;li&gt;
&lt;a href="https://github.com/Marak/Faker.js" rel="noopener noreferrer"&gt;Faker.js&lt;/a&gt; - Generate huge amounts of fake data.&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;I would highly recommend you to bookmark this article. We will upgrade this article based on the suggestion and feedback from all of you. If you like to add/remove something from the list, please let me know in the comments or you can make a pull request &lt;a href="https://github.com/shaikh-shahid/awesome-node#natural-language-processing" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article was first published at &lt;a href="https://codeforgeek.com/awesome-node-js-tools-libraries-and-resources/"&gt;https://codeforgeek.com/awesome-node-js-tools-libraries-and-resources/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A Guide to Securing Node.js Applications</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Wed, 30 Dec 2020 07:59:31 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/a-guide-to-securing-node-js-applications-4bcc</link>
      <guid>https://dev.to/shaikhshahid/a-guide-to-securing-node-js-applications-4bcc</guid>
      <description>&lt;p&gt;The one thing that developers tend to considers at the end of the development cycle is the “security” of the application. A secure application is not a luxury, it’s a necessity. You should consider the security of your application at every phase of the development such as architecture, design, code, and finally the deployment.&lt;/p&gt;

&lt;p&gt;In this tutorial, we are going to learn ways to secure our Node.js application. Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Validation – Never Trust Your Users
&lt;/h2&gt;

&lt;p&gt;You must always validate or sanitize the data coming from the user or other entity of the system. The bad validation or no validation at all is a threat to the working system and can lead to a security exploit. You should also escape the output. Let's learn how to validate the incoming data in Node.js. You can use a node module called &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/validator"&gt;validator&lt;/a&gt;&lt;/strong&gt; to perform the data validation. For example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;validator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo@bar.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//=&amp;gt; true&lt;/span&gt;
&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//=&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use a module called &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/joi"&gt;joi&lt;/a&gt;&lt;/strong&gt; (recommended by Codeforgeek) to perform the data/schema validation. For example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;joi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;joi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;joi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataToValidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shahid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123456&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataToValidate&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;    
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SQL Injection Attack
&lt;/h2&gt;

&lt;p&gt;SQL injection is an exploit where malicious users can pass unexpected data and change the SQL queries. Let's understand with the example. Assume your SQL query looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
    &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;"' + req.body.first_name +  '"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1332&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a normal scenario, you would expect that this query will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
    &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"John"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1332&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if someone passes the first_name as the value shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John", last_name="Wick"; --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, your SQL query will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
    &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;"Wick"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;--" WHERE id=1001;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you observe, the WHERE condition is commented out and now the query will update the users table and sets every user’s first name as “John” and last name as “Wick”. This will eventually lead to system failure and if your database has no backup, then you’re doomed.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to prevent SQL Injection attack
&lt;/h3&gt;

&lt;p&gt;The most useful way to prevent SQL injection attacks is to sanitize input data. You can either validate every single input or validate using parameter binding. Parameter binding is mostly used by the developers as it offers efficiency and security. If you are using a popular ORM such as sequelize, hibernate, etc then they already provide the functions to validate and sanitize your data. If you are using database modules other than ORM such as &lt;a href="https://codeforgeek.com/nodejs-mysql-tutorial/"&gt;mysql for Node&lt;/a&gt;, you can use the escaping methods provided by the module. Let's learn by example. The codebase shown below is using &lt;strong&gt;mysql&lt;/strong&gt; module for Node.&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;var&lt;/span&gt; &lt;span class="nx"&gt;mysql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;mysql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;me&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE users SET ?? = ? WHERE ?? = ?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first_name&lt;/span&gt;&lt;span class="dl"&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;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The double question mark is replaced with the field name and the single question mark is replaced with the value. This will make sure that input is safe. You can also use a stored procedure to increase the level of security but due to lack of maintainability developers tend to avoid using stored procedures. You should also perform the server-side data validation. I do not recommend you to validate each field manually, you can use modules like &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/joi"&gt;joi&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typecasting
&lt;/h3&gt;

&lt;p&gt;JavaScript is a dynamic typed language i.e a value can be of any type. You can use the typecasting method to verify the type of data so that only the intended type of value should go into the database. For example, a user ID can only accept the number, there should be typecasting to ensure that the user ID should only be a number. For example, let's refer to the code we shown above.&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;var&lt;/span&gt; &lt;span class="nx"&gt;mysql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;mysql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;     &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;me&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE users SET ?? = ? WHERE ?? = ?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;first_name&lt;/span&gt;&lt;span class="dl"&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;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you notice the change? We used &lt;strong&gt;Number(req.body.ID)&lt;/strong&gt; to ensure that ID is always the number. You can refer to &lt;a href="https://flaviocopes.com/javascript-casting/"&gt;this beautiful&lt;/a&gt; article by a fellow blogger to understand typecasting in depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Authentication and Authorization
&lt;/h2&gt;

&lt;p&gt;Sensitive data such as passwords should be stored in the system in a secure way that malicious users don't misuse sensitive information. In this section, we will learn how to store and manage passwords which are quite generic, and pretty much every application has passwords in some way in their system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Password Hashing
&lt;/h3&gt;

&lt;p&gt;Hashing is a function that generates a fixed-size string from input. The output from the hashing function cannot be decrypted hence it's "one-way" in nature. For data such as passwords, you must always use hashing algorithms to generate a hash version of the input password string which is a plaintext string. &lt;/p&gt;

&lt;p&gt;You might be wondering that if the hash is a one-way string then how come attackers gain access to passwords? &lt;/p&gt;

&lt;p&gt;Well, as I mentioned above, hashing takes an input string and generates a fixed-length output. So attackers take a reverse approach and they generate the hashes from the general password list, then they compare the hash with the hashes in your system to find the password. This attack is called &lt;strong&gt;lookup tables&lt;/strong&gt; attack. &lt;/p&gt;

&lt;p&gt;This is the reason why you as an architect of the system must not allow generic used passwords in your system. To overcome this attack, you can something called &lt;strong&gt;"salt"&lt;/strong&gt;. Salt is attached to the password hash to make it unique irrespective of the input. Salt has to be generated securely and randomly so that it is not predictable. The Hashing algorithm we suggest you is &lt;strong&gt;BCrypt&lt;/strong&gt;. At the time of writing this article, Bcrypt has not been exploited and considered cryptographically secure. In Node.js, you can use &lt;strong&gt;bcyrpt&lt;/strong&gt; node module to perform the hashing. &lt;/p&gt;

&lt;p&gt;Please refer to the example code below.&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;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;bcrypt&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;saltRounds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some-Password@2020&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;saltRounds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passwordHash&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="c1"&gt;//we will just print it to the console for now&lt;/span&gt;
    &lt;span class="c1"&gt;//you should store it somewhere and never logs or print it&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hashed Password:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passwordHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;SaltRounds&lt;/strong&gt; function is the cost of the hash function. The higher the cost, the more secure hash would be generated. You should decide the salt based on the computing power of your server. Once the hash is generated for a password, the password entered by the user will be compared to the hash stored in the database. Refer to the code below for reference.&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;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;bcrypt&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;incomingPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some-Password@2020&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;existingHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some-hash-previously-generated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;incomingPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;existingHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Valid Password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;//invalid password handling here&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid Password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Password Storage
&lt;/h3&gt;

&lt;p&gt;Whether you use the database, files to store passwords, you must not store a plain text version. As we studied above, you should generate the hash and store the hash in the system. I generally recommend using &lt;strong&gt;varchar(255)&lt;/strong&gt; data type in case of a password. You can opt for an unlimited length field as well. If you are using &lt;strong&gt;bcrypt&lt;/strong&gt; then you can use &lt;strong&gt;varchar(60)&lt;/strong&gt; field because &lt;strong&gt;bcrypt&lt;/strong&gt; will generate fixed size 60 character hashes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authorization
&lt;/h3&gt;

&lt;p&gt;A system with proper user roles and permission prevents malicious users to act outside of their permission. To achieve a proper authorization process, proper roles and permissions are assigned to each user so that they can do certain tasks and nothing more. In Node.js, you can use a famous module called &lt;a href="https://www.npmjs.com/package/acl2"&gt;ACL&lt;/a&gt; to develop access control lists based on authorization in your system.&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;ACL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;acl2&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;acl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ACL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ACL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memoryBackend&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// guest is allowed to view blogs&lt;/span&gt;
&lt;span class="nx"&gt;acl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view&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 if the permission is granted&lt;/span&gt;
&lt;span class="nx"&gt;acl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAllowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;joed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blogs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;view&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;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User joed is allowed to view blogs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checkout the acl2 documentation for more information and example code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bruteforce Attack Prevention
&lt;/h2&gt;

&lt;p&gt;Bruteforce is an attack where a hacker uses software to try different passwords repetitively until access is granted i.e valid password is found. To prevent a Bruteforce attack, one of the simplest ways is to &lt;strong&gt;wait it out&lt;/strong&gt; approach. When someone is trying to login into your system and tried an invalid password more than 3 times, make them wait for 60 seconds or so before trying again. This way the attacker is going to be slow and it's gonna take them forever to crack a password. &lt;/p&gt;

&lt;p&gt;Another approach to preventing it is to ban the IP that is generating invalid login requests. Your system allows 3 wrong attempts per IP in 24 hours. If someone tries to do brute-forcing then block the IP for 24 hours. This rate-limiting approach is been used by lots of companies to prevent brute-force attacks. If you are using the Express framework, there is a middleware module to enable rate-limiting in incoming requests. Its called &lt;strong&gt;express=brute&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;You can check the example code below.&lt;/p&gt;

&lt;p&gt;Install the dependency.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Enable it in your route.&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;ExpressBrute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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-brute&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;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ExpressBrute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MemoryStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// stores state locally, don't use this in production&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bruteforce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ExpressBrute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;store&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="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;bruteforce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prevent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// error 429 if we hit this route too often&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success!&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;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example code is taken from &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/express-brute"&gt;express-brute&lt;/a&gt;&lt;/strong&gt; module documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secure Transmission using HTTPS
&lt;/h2&gt;

&lt;p&gt;It is 2021 and you must use HTTPS to send your data and traffic over the internet securely. HTTPS is an extension of the HTTP protocol with secure communication support. By using HTTPS, you can make sure that the traffic and your user's data over the internet is encrypted and safe. &lt;/p&gt;

&lt;p&gt;I am not going to explain how HTTPS works in the detail here. We are going to focus on the implementation part of it. I highly recommend you to use &lt;strong&gt;LetsEncrypt&lt;/strong&gt; to generate the SSL certificates for all of your domain/subdomain. &lt;/p&gt;

&lt;p&gt;It's free and runs a daemon to update SSL certificates every 90 days. You can learn more about LetsEncrypt &lt;a href="https://letsencrypt.org/getting-started/"&gt;here&lt;/a&gt;. You can opt for a domain-specific certificate or a wildcard certificate if you have multiple subdomains. LetsEncrypt supports both. &lt;/p&gt;

&lt;p&gt;You can use LetsEncrypt for both Apache and Nginx based web servers. I highly recommend performing SSL negotiations in the reverse proxy or at the gateway layer because it is a heavy computing operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session Hijacking Prevention
&lt;/h2&gt;

&lt;p&gt;The session is an important part of any dynamic web application. Having a secure session in the application is a must for the users and systems safety. A session is implemented using cookies and it must be kept secure to prevent session hijacking. The following is a list of the attributes that can be set for each cookie and what they mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;secure&lt;/strong&gt; - this attribute tells the browser to only send the cookie if the request is being sent over HTTPS.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;HttpOnly&lt;/strong&gt; - this attribute is used to help prevent attacks such as cross-site scripting since it does not allow the cookie to be accessed via JavaScript.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;domain&lt;/strong&gt; - this attribute is used to compare against the domain of the server in which the URL is being requested. If the domain matches or if it is a sub-domain, then the path attribute will be checked next.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;path&lt;/strong&gt; - in addition to the domain, the URL path that the cookie is valid for can be specified. If the domain and path match, then the cookie will be sent in the request.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;expires&lt;/strong&gt; - this attribute is used to set persistent cookies since the cookie does not expire until the set date is exceeded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use &lt;strong&gt;express-session&lt;/strong&gt; npm module to perform session management in the Express framework.&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="nx"&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;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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-session&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyboard cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;resave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;saveUninitialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can learn more about Express session handling &lt;a href="https://codeforgeek.com/manage-session-using-node-js-express-4/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross Site Request Forgery (CSRF) Attack Prevention
&lt;/h2&gt;

&lt;p&gt;CSRF is an attack where that manipulates a trusted user of a system to execute unwanted malicious actions on a web application. In Node.js, we can use &lt;strong&gt;csurf&lt;/strong&gt; module to mitigate CSRF attack. This module requires either &lt;strong&gt;express-session&lt;/strong&gt; or &lt;strong&gt;cookie-parser&lt;/strong&gt; to be initialized first. You can check out the example code below.&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="nx"&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;cookieParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;cookie-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csrf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;csurf&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;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// setup route middlewares&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csrfProtection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;csrf&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parseForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// create express app&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// we need this because "cookie" is true in csrfProtection&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cookieParser&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="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;csrfProtection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// pass the csrfToken to the view&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;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send&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;csrfToken&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;csrfToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parseForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;csrfProtection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data is being processed&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="nx"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the web page, you need to create a hidden input type with the value of the CSRF token. For example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/process"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"_csrf"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"{{csrfToken}}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  Favorite color: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"favoriteColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case of AJAX requests, you can pass the CSRF token in the header.&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;var&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;meta[name="csrf-token"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CSRF-Token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Denial of Service
&lt;/h2&gt;

&lt;p&gt;Denial of service or DOS is a type of attack where attackers tried to bring down the service or make it inaccessible to users by disrupting the system. The attacker generally flooded the systems with lots of traffic or requests which in turn increases the CPU and memory load leading to a system crash. To mitigate DOS attacks in your Node.js application, the first step would be the identification of such an event. I highly recommend these two modules to be integrated into the system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Account lockout - After n number of failed attempts, lock the account or IP address for a period of time (say 24h?)&lt;/li&gt;
&lt;li&gt; Rate limiting - Limit the users to request the system n number of times within a specific period, for example, 3 requests per minute from an individual user&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Regular expression Denial of service attack (ReDOS)is a type of DOS attack where the attacker exploits the regular expression implementation in the system. Some regular expression takes heavy computing power to execute and the attacker can exploit it by submitting requests that involve regular expression in the system which in turns increases the load on the system leading to system failure. You can use software like &lt;a href="https://github.com/davisjam/vuln-regex-detector"&gt;this&lt;/a&gt; to detect the dangerous regular expressions and avoid using them in your system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies Validation
&lt;/h2&gt;

&lt;p&gt;We all use tons of dependencies in our projects. We need to check and validate these dependencies as well to ensure the security of the overall project. NPM already has an audit feature to find the vulnerability of the project. Just run the command shown below in your source code directory.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To fix the vulnerability, you can run this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm audit fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run the dry run to check the fix before applying it to your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm audit fix --dry-run --json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  HTTP Security Headers
&lt;/h2&gt;

&lt;p&gt;HTTP provides several security headers that can prevent commonly known attacks. If you are using the Express framework then you can use a module called &lt;strong&gt;&lt;a href="https://helmetjs.github.io/"&gt;helmet&lt;/a&gt;&lt;/strong&gt; to enable all security headers with a single line of code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install helmet --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is how to use it.&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="nx"&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;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;helmet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;helmet&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;helmet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This enables the following HTTP headers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Strict-Transport-Security&lt;/li&gt;
&lt;li&gt;  X-frame-Options&lt;/li&gt;
&lt;li&gt;  X-XSS-Protection&lt;/li&gt;
&lt;li&gt;  X-Content-Type-Protection&lt;/li&gt;
&lt;li&gt;  Content-Security-Policy&lt;/li&gt;
&lt;li&gt;  Cache-Control&lt;/li&gt;
&lt;li&gt;  Expect-CT&lt;/li&gt;
&lt;li&gt;  Disable X-Powered-By&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These headers prevent malicious users from various types of attacks such as clickjacking, cross-site scripting, etc.&lt;/p&gt;

&lt;p&gt;Author's blog: &lt;a href="https://shaikhshahid.com"&gt;https://shaikhshahid.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>security</category>
    </item>
    <item>
      <title>Redis Streams for Beginners</title>
      <dc:creator>Shahid Shaikh</dc:creator>
      <pubDate>Tue, 22 Sep 2020 18:41:27 +0000</pubDate>
      <link>https://dev.to/shaikhshahid/redis-streams-for-beginners-1hll</link>
      <guid>https://dev.to/shaikhshahid/redis-streams-for-beginners-1hll</guid>
      <description>&lt;p&gt;Redis is the most popular key-value database store. Redis is used in the majority of large scale applications.&lt;/p&gt;

&lt;p&gt;While building large scale distributed systems, we often end up in a scenario where we have to perform the huge amount of data ingestion or data transfer from one system to another. The only feasible way to perform this is through streaming. Distributed engineers generally use streaming software such as Apache Kafka to perform data streaming and ingestion.&lt;/p&gt;

&lt;p&gt;Redis with the support of version 5.0 offers an innovative way to manage streams. Redis Stream is a built-in feature and it offers a data structure that developers can use to perform data ingestion, data consumption, creates a data channel between producer and consumers, and so on.&lt;/p&gt;

&lt;p&gt;In this tutorial, we are going to explore how to use Redis streams and how you as a distributed systems engineer can incorporate Redis streams in your architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redis streams capabilities
&lt;/h2&gt;

&lt;p&gt;Redis is used in various use cases across the system. This includes content caching, real-time analytics, message brokers, etc.&lt;/p&gt;

&lt;p&gt;While Redis already provides a publish/subscribe feature, with the release of Redis streams, Redis offers the following capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect large amounts of data.&lt;/li&gt;
&lt;li&gt;Create a data channel between many consumers and producers.&lt;/li&gt;
&lt;li&gt;Data ordering is effectively managed even though the rate of data ingestion and data consumption is different.&lt;/li&gt;
&lt;li&gt;Offline data persistence support.&lt;/li&gt;
&lt;li&gt;Asynchronous communication between producer and consumer.&lt;/li&gt;
&lt;li&gt;Easily scalable to large number producers and consumers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Like I mentioned earlier, Redis streams are built-in into Redis. You don’t need to perform extra installation or management of heavy software. It’s right into Redis.&lt;/p&gt;

&lt;p&gt;Let’s jump right into Redis streams and learn how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Redis Streams
&lt;/h2&gt;

&lt;p&gt;Redis Streams is an append-only log-based data structure. Redis streams offer commands to add data in streams, consume streams, and manage how data is consumed.&lt;/p&gt;

&lt;p&gt;Redis streams can have one to one communication or one to many or many to many communication streams between producers and consumers. Redis streams also offer consumer groups so that they can consume only the information that they are supposed to receive.&lt;/p&gt;

&lt;p&gt;Let’s use Redis streams commands. I am assuming that you have Redis version 5.0 or above already installed in your system. If not, please navigate to the &lt;a href="https://redis.io/download"&gt;Redis download page&lt;/a&gt; to download the latest version of Redis.&lt;/p&gt;

&lt;p&gt;Once you have Redis installation sorted out, start the Redis server if you are using it in your system using the following command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Some installers already run the Redis server in the background, so if you get some error, don’t worry about it.&lt;/p&gt;

&lt;p&gt;Now, let’s start the Redis command line shell using the following command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Let’s add some data in Redis streams. The default and easy way are to run this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XADD mystream * name Shahid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, mystream is the name of the stream. Name is the key and Shahid (My name) is the value.&lt;/p&gt;

&lt;p&gt;When you run this command, Redis will generate the ID for your stream data. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--divP-btO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/rotj2anxjkthkv6jmhl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--divP-btO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/rotj2anxjkthkv6jmhl5.png" alt="Command output" width="599" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also add our own ID while adding the records. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XADD mystream 10000000 name Shahid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you should rely on a system-generated unique ID. &lt;/p&gt;

&lt;p&gt;Let’s consume data from the Redis streams.&lt;/p&gt;

&lt;p&gt;To read everything from the start of the stream to the end, we can use the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XREAD STREAMS mystream 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are giving the name of the stream and start index i.e 0. This command will return all the records present in the stream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dBJ8e8ac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/tx19bc19on8mt7ip6efp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dBJ8e8ac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/tx19bc19on8mt7ip6efp.png" alt="Command Output" width="653" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also limit the records by providing the record count.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XREAD COUNT 100 STREAMS mystream 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also iterate through the stream using the XRANGE command.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XRANGE mystream 1518951123450-0 1518951123460-0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command shown above will read the record from the stream between the ID mentioned in the command.&lt;/p&gt;

&lt;p&gt;If we don’t know the ID of the records, we can pick the number of records using the COUNT operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XRANGE mystream - + COUNT 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command shown above will return the record from 10 records iterating from the beginning of the stream.&lt;/p&gt;

&lt;p&gt;Redis streams offer more commands and ways to manage streams. You can learn more about it on the &lt;a href="https://redis.io/commands/xadd"&gt;documentation&lt;/a&gt; page here.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
