Q:

what the difference between qs and querystring

There is a function bodyparser.urlencoded(options) in body-parser, it has a option called extended.

The extended option allows to choose between parsing the URL-encoded
  data with the querystring library (when false) or the qs library (when
  true). The "extended" syntax allows for rich objects and arrays to be
  encoded into the URL-encoded format, allowing for a JSON-like
  experience with URL-encoded. For more information, please see the qs
  library.

I had read qs and querystring document but I could not find any obvious difference, so I am asking for help here.

A:

Let's check them together:
Query String

The querystring module provides utilities for parsing and formatting
URL query strings.

Node.js v10.0.0 Documentation : API : Query String
It is part of the NodeJS API, introduced in v0.1.25.
We can observe it has 4 main function : escape, parse, stringify, unescape
(all the functions except the parse function have been the same since v0.1.25.)

~ History of querystring.parse :

    Version     Changes
     v8.0.0      Multiple empty entries are now parsed correctly (e.g. &=&=).
     v6.0.0      The returned object no longer inherits from Object.prototype.
     v4.2.4      The eq parameter may now have a length of more than 1.

As you can see it is a simple solution for its main purpose.

qs module :

A querystring parsing and stringifying library with some added
security.

NPM Package : qs  (Github Repo.)
(At the time of writing this)

Last Updated : 2 days ago
Open issues  : 28
( of which 7 are labeled as bug )

Lets just have a glimpse at the qs.parse function :

qs allows you to create nested objects within your query strings, by
surrounding the name of sub-keys with square brackets []. For example,
the string 'foo[bar]=baz' converts to:

assert.deepEqual(qs.parse('foo[bar]=baz'), {
>     foo: {
>         bar: 'baz'
>     } });

Compared to Query String, it is able of parsing nested objects...

By default, when nesting objects qs will only parse up to 5 children
deep. This means if you attempt to parse a string like
'a[b][c][d][e][f][g][h][i]=j' your resulting object will be:
var expected = {
    a: {
        b: {
            c: {
                d: {
                    e: {
                        f: {
                            '[g][h][i]': 'j'
                        }
                    }
                }
            }
        }
    }
};

The depth can be overridden :
var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 8 });

...and this is just one of the many features that this package offers, compared to Query String
The qs.stringify function has also many more options
I would say qs is an advanced solution.

Question :

I had read qs and querystring document but I could not find any
obvious difference, so I am asking for help here.

Answer :
They are not different in terms of purpose.
querystring has some limits, but at the end, that is depending on your needs...

