Validations & Transformations β Lecture Notes
1. Where Validations Fit in the Backend Architecture
A typical backend has three layers:
HTTP Request
β
βββββββββββββββββββββββββββββββββββββββ
β Controller Layer β β HTTP concerns: status codes,
β [Validation & Transformation here] β request/response format
βββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββ
β Service Layer β β Business logic: emails, notifications,
β β webhooks, orchestration
βββββββββββββββ¬ββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββ
β Repository Layer β β DB queries: inserts, updates,
β β deletes, reads
βββββββββββββββββββββββββββββββββββββββ
Validations and transformations happen at the entry point of the Controller layer β after route matching, before any business logic or DB calls are made.
Why so early? Garbage in β garbage out. Catching bad data at the boundary prevents propagation deep into the system and avoids cryptic errors (like a
500 Internal Server Errorfrom a DB type constraint violation instead of a clean400 Bad Request).
2. What is Validation?
Ensuring all incoming data β JSON body, query params, path params, headers β is in the exact format the API expects before any logic runs.
If validation fails β return 400 Bad Request immediately with a descriptive error. No service call, no DB call.
What validation covers: presence of required fields, correct data types, value constraints, structural patterns, logical consistency.
3. Types of Validation
3.1 Type Validation
The most basic: does the field have the correct data type?
| Field | Expected | Received | Result |
|---|---|---|---|
age | number | "25" (string) | β Error |
tags | string[] | [1, 2] (number[]) | β Error |
active | boolean | "false" (string) | β Error |
Works recursively β nested objects and array elements can each have their own type constraints.
3.2 Syntactic Validation
Does the value satisfy a required structural pattern, regardless of semantic meaning?
| Field | Validation | Example Failure |
|---|---|---|
email | Must match local@domain.tld pattern | "notanemail" |
phone | Country code + digit count pattern | "123" |
date | Must be valid YYYY-MM-DD format | "2025-13-45" |
name | Length between 5β100 characters | "ab" |
These are purely structural β a syntactically valid email doesnβt mean the inbox exists.
3.3 Semantic Validation
Does the value make sense in the real world β given its context and business rules?
| Field | Rule | Example Failure |
|---|---|---|
dateOfBirth | Cannot be in the future | 2026-01-01 |
age | Must be between 1β120 | 430 |
endDate | Must be after startDate | endDate < startDate |
Semantic validation catches logically impossible or unrealistic values that pass syntactic and type checks.
3.4 Complex / Cross-Field Validation
Validation rules that span multiple fields or depend on the value of another field.
Examples:
passwordConfirmationmust exactly equalpasswordpasswordmust be at least 8 characters- If
married = true, thenpartnerNameis required (otherwise optional)
{
"password": "secret1", // must be β₯ 8 chars
"passwordConfirmation": "secret1", // must equal password
"married": true,
"partnerName": "Alice" // required only when married = true
}
These dependencies canβt be expressed field-by-field; the validation logic needs access to the full payload.
4. What is Transformation?
Converting incoming data into the format expected by the service layer β before or after validation, as part of the same pipeline.
Why itβs necessary
Query parameters are always strings when they arrive at the server, regardless of what the client intended. A value like ?page=2&limit=20 arrives as { page: "2", limit: "20" }. Validating these as numbers without first casting them will fail β the type check sees strings.
Transformation β cast string "2" to number 2 β then validate > 0 && < 500.
Common transformation operations
| Operation | Example |
|---|---|
| Type casting | "20" β 20 (query param β number) |
| Normalization | "Test@GMAIL.COM" β "test@gmail.com" (email to lowercase) |
| Sanitization | Strip leading/trailing whitespace from strings |
| Formatting | "9876543210" β "+9876543210" (prepend + to phone) |
| Date normalization | "2025-11-05" β ISO 8601 format |
5. The Validation & Transformation Pipeline
Validations and transformations are combined into a single reusable pipeline at the controller entry point β typically a middleware or utility function configured with a schema.
Incoming Request (JSON / query params / path params)
β
ββββββββββββββββββββββββββββββββ
β Validation & Transformation β
β Pipeline (schema-defined) β
β β
β 1. Type casting / transform β
β 2. Presence checks β
β 3. Type validation β
β 4. Syntactic validation β
β 5. Semantic validation β
β 6. Cross-field validation β
ββββββββββββ¬ββββββββββββββββββββ
β
Pass ββββΌβββ Fail β 400 Bad Request + error details
β
Controller β Service β Repository
Keeping everything in one place means you never have to hunt across layers to understand what an API expects.
6. Frontend vs Backend Validation
A critical distinction that is often misunderstood:
| Frontend Validation | Backend Validation | |
|---|---|---|
| Purpose | User experience β immediate feedback | Security & data integrity |
| When it runs | Before the API call | After the API call reaches the server |
| Can be bypassed? | Yes β Postman, curl, direct API calls | No β always runs |
| Required? | Recommended, not mandatory | Mandatory |
Never rely on frontend validation for security. A server has many clients β a web app, a mobile app, Postman, curl, other servers. Only the backend can enforce constraints unconditionally.
Bad assumption: "Our React form validates the email, so the backend doesn't need to"
Reality: Anyone can call POST /api/users with a raw HTTP request and bypass the form entirely
Rule: Design backend validations independently of whatever the frontend does. Frontend validation is a UX courtesy; backend validation is a security requirement.
7. Summary
| Concept | Definition | Location |
|---|---|---|
| Type validation | Check data types match expected types | Entry point of controller |
| Syntactic validation | Check value matches a structural pattern (email, phone, date) | Entry point of controller |
| Semantic validation | Check value is logically meaningful (DOB not in future, age β€ 120) | Entry point of controller |
| Complex validation | Cross-field rules (password match, conditional required fields) | Entry point of controller |
| Transformation | Cast/normalize/format data before passing to service layer | Entry point of controller |
Quick Revision Checklist
- Validations run at the controller entry point β after route match, before any service/DB calls
- Failed validation β
400 Bad Requestwith descriptive error; never let bad data reach the service layer - Type validation: correct data type (string, number, boolean, array)
- Syntactic validation: structural pattern match (email, phone, date format, string length)
- Semantic validation: logical correctness (DOB not in future, age within realistic range)
- Complex validation: cross-field rules (password confirmation, conditional required fields)
- Transformation: cast types (query params are always strings β cast to number), normalize (email β lowercase), format (phone β add
+) - Validation + transformation live in one pipeline β single source of truth for input contract
- Frontend validation = UX only; Backend validation = security + data integrity; never substitute one for the other
- Validation errors double as implicit API documentation β empty payload returns all expected fields