Zod is 150x times slower than regular typeof checks

TLDR

Zod is a tool for Typescript that allows you to validate types during runtime. It has 30K ⭐️ stars on Github, is used by 1M people, and has over 300 contributors. It also has 8.7 weekly downloads on npm. However, there’s a catch. It’s 150 times slower than using regular typeof checks! The benchmark code can be found at the end of the article.

Zod Benchmark

Choosing convenience instead of performance

It seems to me that many modern programmers are neglecting efficiency. They built resource hungry tools & applications with unnecessary features. Back in time, slow code considered garbage people used to focused more on performance than convenience. Unfortunately, not every company has the luxury of running expensive servers or paying high costs for various software services and expensive instances. Most of companies are SMEs and can’t afford huge AWS bills.

More open source projects are suffering

Consider Express.js as an example. Compared to a basic native http server it’s considered slow but it’s a great tool for saving coding time. Next.js is 14.5x slower than rendering with pure react https://github.com/eknkc/ssr-benchmark. Various back-end and front-end frameworks are on this list. Fortunately new solutions (at least for backend) come to the rescue with tools like llrt or Bun.

Budget infrastructure

My hope is that more importance will be given to performance in future software development. This would allow smaller businesses to run their systems using fewer resources. We’ve seen SaaS/PaaS companies rising prices overnight and migration is pain in the butt. Clients and managers won’t cover additional costs and will ask for migration to alternative cheap services, while only a few may decide to absorb the added expenses.

Code is used for benchmark

Zod

import { z } from "zod";

const personSchema = z.object({
  name: z.string(),
  age: z.number(),
});


const start = performance.now();
for (let i = 0; i < 10000000; i++) {
    zod();
}
const end = performance.now();
console.log(`Parsing took ${end - start} ms`);


function zod(){
    return personSchema.parse({
        name: "John Doe",
        age: 30,
    });
}

Plain

const start = performance.now();
for (let i = 0; i < 10000000; i++) {
    plain()
}
const end = performance.now();
console.log(`Parsing took ${end - start} ms`);


function plain(){
    const obj = {
        name: "John Doe",
        age: 30,
    };
    if (typeof obj!== "object" || obj === null) {
        throw new TypeError("Expected object");
    }
    if (typeof obj.name!== "string") {
        throw new TypeError("Expected string");
    }
    if (typeof obj.age!== "number") {
        throw new TypeError("Expected number");
    }
    return obj
}
Follow me on Twitter! It's free!