Validation answer

Client validation improves user experience. Server validation protects the system.

Treat the browser as a helpful client

Form validation is searched constantly because it affects UX and security at the same time.

Divide feedback from enforcement

The browser can help users correct mistakes, but the server must be the source of truth because clients can be bypassed.

Layer Job
Client Fast feedback, required fields, friendly formatting
Server Security, uniqueness, permissions, trusted rules
Database Constraints that protect data permanently

Trace one signup request

const email = formData.get("email");

if (typeof email !== "string" || !email.includes("@")) {
  return { ok: false, field: "email", message: "Enter a valid email." };
}

This example is intentionally small. In a real codebase, the surrounding details matter: naming, error handling, tests, runtime config, permissions, and how easy the next developer can understand the change.

Validate again at the state boundary

  • Validate on submit server-side.
  • Show client errors before submit when possible.
  • Return field-level errors in a stable shape.
  • Keep database constraints for critical uniqueness.
  • Avoid exposing sensitive validation details.

Validation designs that fail

  • Trusting HTML required as security.
  • Showing one generic error for every field.
  • Validating differently on client and server.
  • Forgetting async checks like email uniqueness.
  • Letting disabled buttons replace real validation.

Describe the trust boundary

Use a concrete sentence:

I used this pattern because [problem]. The main tradeoff was [tradeoff]. I verified it by [test or check].

That structure works because it shows judgment. Anyone can name a tool. Strong developers explain why they chose it, what could go wrong, and how they checked the result.

Standards and references

One rule for both layers

Client validation improves user experience. Server validation protects the system. Keep the implementation small, verify the edge cases, and write the decision down so the next person can trust it.

Prove that server validation cannot be bypassed

The fastest useful test is not another browser click. Send the request directly with curl, Postman, or an integration test and omit the client entirely. Change a disabled field, send a negative amount, repeat a supposedly unique username, and include an unexpected property. The server should reject each invalid state with a stable error code.

For a money-moving workflow such as CryptoEx, the browser may warn that an amount exceeds the displayed balance. The server must still load the authoritative balance and reserve funds inside a database transaction. A stale tab, modified JavaScript, or direct HTTP client can bypass every React check.

const input = withdrawalSchema.parse(req.body);

await db.transaction(async (tx) => {
  const account = await tx.account.lockForUpdate(input.accountId);
  if (account.available < input.amount) {
    throw new DomainError('INSUFFICIENT_FUNDS');
  }
  await tx.withdrawal.create(input);
  await tx.account.reserve(input.amount);
});

The schema protects shape and basic ranges. The transaction protects a business invariant that depends on current state. Those are different jobs.

Keep messages useful without leaking internals

Return field-level feedback for expected input mistakes, but do not send database errors, stack traces, or raw policy rules to the browser. Log the internal cause with a request ID and return a stable public code. This gives the UI something reliable to render without turning an error response into a debugging dump for an attacker.

Questions for a validation review

Can a direct HTTP client bypass the browser rule? Does the server validate current state inside the same transaction that changes it? Are unknown fields rejected or ignored deliberately? Do public errors help the user without exposing internal policy or database details?

Finally, test accessibility. Error text should be connected to the field, announced to assistive technology, and preserved long enough to act on. Client validation is user interface work; server validation is enforcement. A good form needs both.