DEV Community

Cover image for I made Express faster than Fastify (100x faster JSON, also NestJS)

I made Express faster than Fastify (100x faster JSON, also NestJS)

Jeongho Nam on April 03, 2023

Outline Hello, I am developer of typia, and studying fastify in nowadays. During the study, I could understand why fastify is faster t...
Collapse
 
metcoder profile image
Carlos Fuentes

Nice work with typia, the job done has been amazing :)
Would you be willing to create a Fastify plugin for typia?
The results can be amazing! Happy to help you with it.

I’m part of Fastify team btw, in case you would like to share some thoughts or doubts about Fastify :)

Collapse
 
samchon profile image
Jeongho Nam • Edited

Got it, I'll try at next Sunday (not tomorrow).

Anyway, where the plugin would be placed in? Just in my github account? Or as a fastify repo?

Collapse
 
metcoder profile image
Carlos Fuentes

Sure thing!

Yeah, made everything within a repo of your authorship and once done, we can incorporate it at the list of community plugins :)
Feel free to ping me out if you want a second pair eyes!

Thread Thread
 
samchon profile image
Jeongho Nam • Edited

What is your github accout name?

I will write an issue on fastify repo tagging you, and need to debate about below:

import fastify from "fastify";
import typia from "typia";

const plugin = fastify().addSomePlugin();
plugin.post("/some-path", {
    schema: {
        body: typia.application<[MyRequestDto]>(),
        response: typia.application<[MyResponseDto]>(),
    },
});
Enter fullscreen mode Exit fullscreen mode

At first, fastify provides plugin interfaces only through the JSON schema defition. As typia can generate JSON schema, it is possible to utilizing current plugin interface of fastify like above.

However, typia is a transformer library generating optimal code in the compilation time, utilizing pure TypeScript type. To maximize strength of typia and make users to be much convenient, I think below code would be should be possible.

import fastify from "fastify";
import typiaProvider from "@fastify/type-provider-typia";

const server = fastify();
const wrapper = typiaProvider.install(server);

wrapper.post<{
    query: SomeQueryDto;
    body: SomeRequestBodyDto;
    response: SomeResponseBodyDto;
}>("/some-path", (req, rep) => {
    req.query // -> type checked SomeQueryDto
    req.body // -> type checked SomeRequestBodyDto
    rep.send({ ... }); // -> faster stringify with type assertion (SomeResponseBodyDto)
    req.headers; // -> no type checking because not specified
});
Enter fullscreen mode Exit fullscreen mode

The typiaProvider.post<T>() function will generate both type assertion (+ JSON serialization when response) and JSON schema definition for Swagger at the same time. Of course, above code requires modifications from plugin APIs of fastify. Therefore, I need to debate about it detaily as an issue.

p.s) I'm developing protobuf features, therefore when fastify accepts typia as a plugin, you can easily support protobuf typed routers very easily.

Thread Thread
 
metcoder profile image
Carlos Fuentes

Hey! Please reach out in GH as metcoder95!

Wow, that sounds interesting. What modifications are you looking for exactly?
In theory, the fastify.register should provide you access to the encapsulated context where the plugin is being added, and therefore decorate any possible route being register through fastify.<post | get | ...>.
But please, open an issue at fastify repo and we can help you sorting things out :)

Thread Thread
 
samchon profile image
Jeongho Nam

Sorry for late.

I've been making guide documents of typia and nestia in nowaydays, and such documentation works had consumed much more time than what I'd expected. Therefore, could not develop the plugin in this weekend.

Anyway, stuyding fastify, I understood that there're enormous things to develop to adjust transform library typia in fastify. There are already a lot of elements to be developed, so I'm going to make a fastify plugin like nestia, which can build SDK library.

Please wait for one to two months, then I'll take interesting plugin.

Thread Thread
 
metcoder profile image
Carlos Fuentes

Please, do not rush it. Happy to wait for the results, please let me know if you need any support or similar. Happy to support you with anything!

Thread Thread
 
samchon profile image
Jeongho Nam • Edited

Currently, succeeded to support fastify through nestia in NestJS.

nestia.io/docs/
github.com/samchon/nestia/tree/mas...

Now, only "Swagger to NestJS" converter project is left for me. It may requires 2~3 weeks, and I'll start the pure fastify plugin project after that. Also, I'll run benchmark fastify + typia, too. Thanks for waiting.

Thread Thread
 
metcoder profile image
Carlos Fuentes

Hey! That's amazing! Don't worry about the plugin, take your time :)

Collapse
 
melroy89 profile image
Melroy van den Berg

So at this point I'm wondering if the benefits of nestia for Fastify can't be embedded upstream (as in making it fast by default when just using fastify)?

Collapse
 
sergeyt profile image
Sergey Todyshev

It would be nice if JSON.stringify function will be optimized on runtime level. And apparently this is doable.

Collapse
 
samchon profile image
Jeongho Nam

Wow, you're planning to send a PR?

Collapse
 
sergeyt profile image
Sergey Todyshev

It is huge effort. I can explain the idea some day :). It seems V8 devteam is not super interested in this now since they are busy enough with other stuff.

Thread Thread
 
samchon profile image
Jeongho Nam

Is it really possible to enhance native JSON.stringify() function?

Thread Thread
 
sergeyt profile image
Sergey Todyshev • Edited

Sure, let me give you a "strange" clue. You can take a look on history of how JSON serialization was improved in .NET world. Similar way native JS objects can have some internal methods for reading and writing from reader/writer objects (that hides content streaming under the hood). After that JSON.stringify and JSON.parse are just tiny wrapper under internal JSON serialization pipeline. But again this work should be done in JS engine (v8 or deno). Hope this helps 😄

Collapse
 
thebrown profile image
Saleumsack

Great article!

Collapse
 
carrotfarm profile image
carrot-farm

잘보고 있습니다.!

Collapse
 
samchon profile image
Jeongho Nam

엌... 태양토끼님 반갑읍니다

Collapse
 
samchon profile image
Jeongho Nam

As I've promised, wrote an article introducing how to use typia in NestJS.

dev.to/samchon/nestia-boost-up-you...

Collapse
 
eram profile image
eram • Edited

Hi. One thing I don't get in your benchmarks: in your Fastify code you are running with a schema validator, but in your Express code you are only replacing the default JSON parsing. How is that even comparable?

Collapse
 
samchon profile image
Jeongho Nam • Edited

Benchmark program of current article does not have request body data. It has only response body data. Therefore, if your "schema validator" means a response data validation before JSON serialization, I wanna say that typia.isStringify() and typia.assertStringify() are doing it.

Otherwise, you're meaning request DTO validation, and what you want to say is "this benchmark program does not handle request DTO validation", I want to introduce below article. Although below article's benchmark program is not measuring the pure request DTO validation logic of fastify, I think it may helpful for you.

By the way, reading your comment, I think that I should enhance above linked article's benchmark program. I'll add pure-fastify component in the benchmark pogram, so that resolve your question clearly. By the enhancement, five componets would be compared:

  • NestJS + express
  • NestJS + fastify
  • NestJS + nestia + express
  • NestJS + nestia + fastify
  • pure fastify
Collapse
 
samchon profile image
Jeongho Nam
Collapse
 
guridocodigo profile image
Guri do Código

And how is the development of the plugin for fastify going?

Thread Thread
 
samchon profile image
Jeongho Nam

Plan to start at 2023-09. Sorry for delaying

github.com/samchon/schedules/blob/...

Thread Thread
 
guridocodigo profile image
Guri do Código • Edited

Thanks, and do you intend to support SWC?

Thread Thread
 
samchon profile image
Jeongho Nam

Not possible to support SWC, because it removes every types like Babel

Collapse
 
olyno profile image
Olyno

Amazing work! I have one question: why did you create external dependencies instead of creating a pull request to the different projects mentioned (NestJS and Express)?

Collapse
 
samchon profile image
Jeongho Nam

About NestJS

NestJS has used class-validator, class-transformer and @nestjs/swagger for many years.

Unless those libraries have lots problems especially in productivity and performance, too much time have passed and strong dependencies had been occured.

Therefore, I think nestia can't be standard feature of NestJS, because of ordinary (legacy) projects.

About Express

express does not restrict any special validation and serialization logic.

Therefore, whatever user choose, it is up to the user.

Collapse
 
olyno profile image
Olyno

Sorry if I wasn't clear. What I meant was that even if NestJS is buried in old code, why not make a big pull request including the Nestia parts? It's a lot of work, but would improvde the DX of a lot of developers

Thread Thread
 
samchon profile image
Jeongho Nam • Edited

Had tried very long time ago ToT.

I got answered that it would better to make a 3rd party library, and it is the nestia.

github.com/samchon/nestia

Collapse
 
kildo162 profile image
KhanhND

I think you can 1.000.000x faster with you using protobuf

Collapse
 
samchon profile image
Jeongho Nam • Edited

You must be a genius who can see the future.

Next version of typia will support protobuf features like below.

export function message<T>(): string; // Protocol Buffer message
export function assertDecode<T>(buffer: Uint8Array): T; // safe decoder
export function assertEncode<T>(input: T): Uint8Array; // safe encoder
Enter fullscreen mode Exit fullscreen mode

For example, I'll introduce a directory storing protobuf schema files generated by the next version of typia.message<T>() function:


p.s) Protobuf is not such faster as you think. I'll come back with new benchmark after the next version.

Collapse
 
kildo162 profile image
KhanhND

I suggest you can use option on proto file for gen code. "option optimize_for = CODE_SIZE;"

Thread Thread
 
samchon profile image
Jeongho Nam

Yes, current typia.message<T>() function writes too much long name. I need to make it shorter.

Collapse
 
tamusjroyce profile image
tamusjroyce

How do these compare on deno instead of node?

Collapse
 
samchon profile image
Jeongho Nam • Edited

Because I do not use deno, I do not know how it would be.

Also, deno does not support standard TypeScript compiler, it is hard (possible but not easy to configure) to test in the deno environment.

Collapse
 
pterpmnta profile image
Pedro Pimienta M.

Deno dont support Typescript?

Thread Thread
 
samchon profile image
Jeongho Nam

Dono does not support TypeScript compiler API