Fix the design · Incident triage

Missing Validation: The API That Trusts Whatever the Client Sends

A create-order path copies client fields straight into an Order entity, and QA was able to save invalid rows that later showed up as support tickets and server errors.

In a low-level design interview, the interviewer opens createOrder() and explains that QA saved invalid rows in the database, then asks what is wrong with how input is handled.

We need your help. Identify what is wrong with how input is handled, then fix the path from “client sends an order” → “row saved” so invalid quantity, email, and product id never reach the database — even when the mobile app already checks inputs.

Problem

Fix the team’s existing create-order path — it already maps client JSON onto an Order entity and saves it without a server-side validation step.

Incident summary

  • QA saved orders with quantity -1 and an email that was not a real email address.
  • Support finds nonsense rows in the orders table.
  • Fuzz testing crashes when productId is null.
  • Nobody added a server validation step because the mobile team said they already check inputs.

Assumptions made by the team

  • The mobile app validates input, so the API does not need to.
  • Database constraints will catch every bad value.
  • Input can be cleaned up later in SQL if problems appear.
  • Adding validation will slow down the API too much.

Impacted services

  • Controller (degraded) — Accepts any JSON shape — no 400 for bad input.
  • Order service (critical) — No validation before persistence.
  • Database (degraded) — Stores invalid business data.
  • Support / QA (degraded) — Chasing bad rows and crash reports.

Triage questions

  1. What is wrong with how this endpoint handles input?
  2. Add validation before orderRepo.save(). Would you use field rules on the request object or a separate validator class? Pick one and name two checks (e.g. quantity, email).
  3. Why should the API validate even if the client checks inputs?
  4. If we add a discount percent field, where does that check go — and when is a database rule enough on its own?

← All design challenges

Loading scenario…