RPC

Light Validation

Benchmarks for an Update Simple User endpoint with light validation and JSON round trip.

A ~100 byte user update: light validation and the JSON round trip, on top of routing and framework overhead.

See the code

Requests per Second

$ loading benchmark…

Throughput

$ loading benchmark…

Latency

$ loading benchmark…

Max Memory

$ loading benchmark…

Max CPU

$ loading benchmark…

Benchmark Code

Each request is an updateSimpleUser call with a simple User model.

interface SimpleUser {
  id: number;
  name: string;
  surname: string;
  lastUpdate: Date;
}

// ### mion ###
// user arrives validated and deserialized: Date fields are Date objects, not JSON strings
export const routes: Routes = {
  updateSimpleUser: (ctx, user: SimpleUser): SimpleUser => {
    user.lastUpdate = new Date();
    return user;
  },
};

// ### Other frameworks (Express, Hapi, Hono) ###
// Zod validates and coerces dates, compiled for speed
const UserSchema = z.compile(z.object({
  id: z.number(),
  name: z.string(),
  surname: z.string(),
  lastUpdate: z.coerce.date(),
}));

app.post("/updateSimpleUser", function (req, res) {
  const user = UserSchema.parse(req.body);
  user.lastUpdate = new Date();
  res.json(user);
});

Reading the Results

Requests take longer than in the 'hello world' benchmark, mostly because of validation and the JSON round trip.

Here, the validation and JSON round trip libraries can matter as much as the routing and framework.

SimpleUser has only 4 fields, so Zod is quick and this mostly measures HTTP handling. That is why http-node, a bare http.createServer with no framework, beats Express, Fastify, Hapi and Hono on Node.js.
Copyright © 2026