intermediate

Express validation

Validate params, query, body, headers, auth context, payload size, and normalized DTOs before application logic runs.

Validate params, query, body, and headers at the HTTP boundary before business logic runs. Schema libraries (Zod, Joi, valibot) parse unknown input into typed DTOs and produce structured validation errors.

					const createUserSchema = z.object({
  email: z.string().email(),
  age: z.coerce.number().int().min(18),
});

function validateBody(schema) {
  return (req, res, next) => {
    const result = schema.safeParse(req.body);
    if (!result.success) return next(new ValidationError(result.error));
    req.dto = result.data;
    next();
  };
}
				

Coerce types deliberately (`z.coerce.number`), enforce payload size limits in the parser, and reject unknown keys when strict contracts matter. Attach normalized DTOs to `req` so handlers never read raw `req.body`.

On interviews: contrast validation middleware versus manual `if` checks, how to return field-level errors (422), and why validation belongs before auth when possible to reduce attack surface.

Common pitfalls: trusting `req.body` after partial checks, no max body size, and different validation rules per route without shared schemas.

The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.

Checklist:

  • Validate all external input at the boundary.
  • Use shared schemas for create/update variants.
  • Return structured, field-aware error responses.
  • Set parser limits and reject oversize payloads.