RPC
Heavy Validation
Benchmarks for an Update User endpoint with heavy validation and JSON round trip.
A ~1 KB user update: heavy validation and the JSON round trip, on top of routing. It compares Zod and TypeBox with RunTypes.
See the codeRequests per Second
Throughput
Latency
Max Memory
Max CPU
Benchmark Code
Each request is an updateUser call with a complex User model.
export interface User {
id: number;
username: string;
email: string;
profile: {
firstName: string;
lastName: string;
displayName: string;
bio?: string;
avatarUrl?: string;
dateOfBirth: Date;
};
role: "admin" | "user" | "guest" | "moderator";
status: "active" | "suspended" | "pending_verification" | "deactivated";
address: Address;
paymentMethods: PaymentMethod[]; // Discriminated union
preferences: UserPreferences;
createdAt: Date;
updatedAt: Date;
lastLoginAt?: Date;
tags: string[];
}
// ### mion ###
// user arrives validated and deserialized: Date fields are Date objects, not JSON strings
export const routes: Routes = {
updateUser: (ctx, user: User): User => {
user.updatedAt = new Date();
user.lastLoginAt = new Date();
user.profile.displayName = `${user.profile.firstName} ${user.profile.lastName.charAt(0)}.`;
return user;
},
};
// ### Other frameworks (Express, Hapi, Hono) ###
// Zod validates and coerces dates, compiled for speed
const UserSchema = z.compile(z.object({
id: z.number(),
username: z.string(),
// ... full schema with nested objects, discriminated unions, etc.
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
// ...
}));
app.post("/updateUser", function (req, res) {
const user = UserSchema.parse(req.body);
user.updatedAt = new Date();
user.lastLoginAt = new Date();
user.profile.displayName = `${user.profile.firstName} ${user.profile.lastName.charAt(0)}.`;
res.json(user);
});
Reading the Results
Requests take much 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 more than the routing.
The more validation and JSON round trip a request needs, the better mion performs, thanks to its optimized JIT RunTypes functions.