Types alone do not validate requests
TypeScript disappears at runtime. A request coming from a browser, mobile client, or third-party integration can still contain missing fields, incorrect types, or unexpected values. Runtime validation closes that gap.
Define one schema at the boundary
A Zod schema can describe the expected payload and produce a typed result after parsing. Keep the schema close to the API contract, validate before business logic runs, and return a consistent error shape to the client.
const CreateUser = z.object({
name: z.string().min(2),
email: z.string().email(),
});
const input = CreateUser.parse(requestBody);Validate more than the body
Path parameters, query strings, headers, uploaded files, and environment variables are all external input. Applying the same discipline to every boundary prevents many production-only bugs.
Keep error messages useful
Do not expose stack traces or internal implementation details. Return field-level messages that help a user correct their input while logging the full diagnostic context on the server.
