Your Application Shouldn’t Trust the Data It Receives
Every application accepts data.

Your Application Shouldn’t Trust the Data It Receives
Every application accepts data.
A name.
An email address.
A password.
A search query.
An order quantity.
A date.
Sometimes that data comes from a form. Sometimes it comes from another application. Sometimes it comes from an API client you’ve never seen before.
And here’s the uncomfortable part:
Your application shouldn’t automatically trust any of it.
Not because every user is malicious.
Simply because the application cannot assume that incoming data follows the rules it expects.
This is where validation and transformations become important.
I spent some time learning about these concepts today, and what initially looked like a simple topic turned into a much bigger part of application design.
The basic idea is:
Data comes in
↓
Is it acceptable?
↓
Validation
↓
Should its representation change?
↓
Transformation
↓
Business logic
The deeper technical breakdown is on my portfolio:
Read the full Validation & Transformations breakdown →
But here’s what I learned.
Validation Is More Than “Required”
Imagine you’re creating an account.
You enter:
Name: Vishal
Age: 24
Email: vishal@example.com
Everything looks fine.
But the application still needs to check the information before using it.
For example:
Is the name actually text?
Was the name provided?
Is the email written correctly?
Is the age a number?
Is the age within an acceptable range?
That’s validation.
In simple terms:
Validation is checking whether incoming information follows the rules the application expects.
And those rules aren’t all the same.
The First Question: Is It the Right Kind of Data?
Suppose an application expects:
Age → number
But it receives:
Age → "24"
The value looks reasonable to a human.
But technically, these are different:
24
and:
"24"
One is a number.
The other is text containing a number.
Whether the application should accept this depends on its contract.
This is type validation.
The question is:
“Did I receive the kind of value I expected?”
Then Comes Format
Suppose you receive:
vishal@example.com
The application can check whether it follows an expected email format.
Compare that with:
vishal@@example
The second value doesn’t follow the expected structure.
This is generally referred to as syntactic validation.
It asks:
“Does this information follow the expected format?”
This applies to many things:
Email addresses
Phone numbers
URLs
Dates
Usernames
IDs
But there’s an important limitation.
Something can look correct and still be wrong.
The Information Can Be Correctly Formatted and Still Make No Sense
Consider:
Age: -10
It’s a number.
So the type is correct.
There’s nothing particularly strange about the way the number is written.
But an age of -10 doesn't make sense under normal application rules.
Or imagine:
Start date: December 20
End date: December 10
Both dates could individually be valid.
But together they may violate the application’s rules.
This is semantic validation.
It asks:
“Does this information make sense in the context where we’re using it?”
That’s an important difference:
Syntactic
→ Is it correctly formatted?
Semantic
→ Does it make sense?
Think About an Online Store
Let’s say you’re buying a laptop.
Your request contains:
{
"productId": "abc123",
"quantity": 5
}
The application can validate:
productId → correct type
quantity → number
quantity → positive
quantity → within allowed range
But there’s another layer.
What if:
productId doesn't exist?
Or:
product exists
but is out of stock
Or:
the user isn't allowed to purchase it
These aren’t simply questions about whether the input is written correctly.
They’re questions about the rules of the application.
This is where validation starts touching business logic.
Validation Isn’t Transformation
Now imagine the user enters:
" Vishal "
The information may be perfectly acceptable.
But the application might prefer to work with:
"Vishal"
The application has changed the representation.
That’s a transformation.
Another example:
" VISHAL@EXAMPLE.COM "
could become:
"vishal@example.com"
if the application’s rules say that this normalization is appropriate.
So:
Validation
→ Is it acceptable?
Transformation
→ How should we represent it?
They’re related, but they’re not the same operation.
Why Transform Data at All?
Consistency.
Imagine different users entering the same information in slightly different ways:
Vishal
VISHAL
vishal
Vishal
Vishal
If these representations should be treated as equivalent for a particular field, the application may normalize them.
The goal is to make downstream processing predictable.
Instead of every part of the application asking:
"Does this have spaces?"
"Is this uppercase?"
"Is this represented differently?"
you can establish a consistent representation earlier.
For example:
Incoming data
↓
Validate
↓
Normalize
↓
Internal representation
But Don’t Transform Everything
This is where things get subtle.
Transformation isn’t automatically good.
Suppose a user enters:
Password123
You shouldn’t casually transform it into:
password123
because you’ve changed the actual value.
Similarly, you shouldn’t blindly lowercase every piece of text just because it looks convenient.
Some values are case-sensitive.
Some values intentionally preserve their original formatting.
The correct question is:
“Does the application consider these different representations equivalent?”
If yes, normalization may make sense.
If not, preserve the original value.
Client-Side Validation Feels Like the First Line
You’ve probably seen this many times.
You type:
abc
into an email field.
Immediately the browser says:
“Please enter a valid email address.”
That’s useful.
The application doesn’t need to send an obviously incorrect request to the server just to discover the mistake.
This is client-side validation.
Its main purpose is:
Better user experience.
It gives immediate feedback.
But there’s a problem.
The browser belongs to the user.
The Server Can’t Trust the Browser
Imagine the frontend says:
Age must be greater than 18.
A user can simply bypass the frontend.
They could send a request directly to the API:
{
"age": 12
}
If the server blindly trusts the request because:
“The frontend already checked it.”
you have a serious architectural mistake.
The server must perform its own validation.
So I think of it like this:
Client-side validation
↓
Helps the user
Server-side validation
↓
Protects the application
Both are useful.
They simply have different jobs.
TypeScript Doesn’t Solve This Problem
This was another useful distinction.
You might write:
function createUser(user: User) {
// ...
}
and assume:
“The function requires a
User, so the data must be valid."
Not at an HTTP boundary.
TypeScript helps you catch problems while developing your application.
But an external request arrives at runtime.
The TypeScript compiler doesn’t inspect every HTTP request sent to your server.
So you still need runtime validation.
The difference is:
TypeScript
→ Helps developers reason about code
Runtime validation
→ Checks actual incoming data
This distinction becomes extremely important when building APIs.
What Happens Inside a Good Request Pipeline?
A backend request might conceptually move through something like:
HTTP Request
↓
Parse
↓
Check structure
↓
Check types
↓
Check format
↓
Transform / normalize
↓
Check semantic rules
↓
Business logic
↓
Database
Not every application will implement these steps in exactly this order.
Some transformations need to happen before certain validations.
Some business rules require database access.
But the important idea is:
Don’t allow raw external input to flow unchecked through your entire application.
This Is Where Schemas Become Useful
Instead of scattering validation throughout your codebase, you can describe the expected shape of a request.
For example:
CreateUser
├── name → string
├── email → valid email
└── age → integer
A validation schema can then determine whether the incoming data satisfies that contract.
In the TypeScript ecosystem, tools such as:
- Zod
- Joi
- Yup
- Valibot
- Ajv
can help implement these contracts.
The library isn’t the interesting part.
The architectural idea is.
You want something close to:
Untrusted Request
↓
Validation Schema
↓
Validated Data
↓
Application
What About Invalid Fields?
Suppose the request is:
{
"name": "",
"age": "hello",
"email": "not-an-email"
}
A useful API shouldn’t simply respond:
Bad request.
It can provide structured information such as:
{
"error": "Validation failed",
"fields": {
"name": "Name is required",
"age": "Age must be a number",
"email": "Invalid email format"
}
}
This makes the API easier to consume.
But error messages should still avoid exposing internal implementation details.
The user needs to know how to fix the request.
They don’t need a database stack trace.
Validation Can Protect Resources Too
Validation isn’t only about correctness.
Consider pagination.
Someone requests:
limit=20
That’s reasonable.
But what if someone requests:
limit=100000000
The value might technically be a number.
But allowing it could cause your server to perform an unreasonable amount of work.
So a good API might define:
limit >= 1
limit <= 100
The same principle applies to:
- string lengths
- array sizes
- uploaded file sizes
- request body sizes
- pagination limits
- batch operations
A value can be valid in isolation but still be unacceptable because of its impact on the system.
Not Every Rule Belongs in Validation
Consider:
quantity must be a positive integer
This is a straightforward input constraint.
Now consider:
Premium customers can purchase 50 units.
Standard customers can purchase 10.
That’s a business rule.
It depends on who the user is and what the current product policy says.
You don’t want your input schema to become a giant container for every business rule in the application.
A cleaner mental model is:
Input validation
↓
"Is this request well-formed?"
Business logic
↓
"Is this operation allowed?"
The exact boundary varies by architecture, but keeping the concepts separate makes systems easier to reason about.
Some Rules Belong to the Database
Consider usernames.
You might first check:
"codemonkey" is available
Then create the user.
But what happens if two requests arrive at nearly the same time?
Request A → available
Request B → available
Request A → create
Request B → create
An application-level check isn’t enough to guarantee uniqueness under concurrency.
The database should enforce the invariant:
username UNIQUE
This gives us another useful model:
Client
↓
Helpful validation
Server
↓
Request validation
Business layer
↓
Business rules
Database
↓
Critical invariants
Each layer contributes something different.
The Security Angle
Validation isn’t a complete security solution.
But it is part of your application’s defensive boundary.
You should consider things like:
Unexpected fields
Oversized input
Unexpected types
Invalid formats
Invalid ranges
Malformed structures
At the same time, validation shouldn’t be used as a replacement for other security controls.
For example:
Validation does not replace parameterized database queries.
Validation does not replace safe output handling for XSS.
Validation does not replace authentication or authorization.
Different problems require different controls.
The Bigger Lesson
Before studying this topic, it was easy to think of validation as:
if (!email) {
return error;
}
But the deeper I went, the more I realized that validation is really about trust boundaries.
Your application sits between two worlds:
External World
│
│ Untrusted data
▼
┌───────────────────┐
│ Application │
│ Boundary │
│ │
│ Validate │
│ Transform │
│ Establish rules │
└───────────────────┘
│
▼
Internal System
The application needs a predictable representation before its internal components start making assumptions about the data.
That’s the real value of validation.
The Mental Model I’m Keeping
I find this model useful:
Incoming Data
↓
Can I parse it?
↓
Is the shape right?
↓
Are the types right?
↓
Is the format right?
↓
Does it make sense?
↓
Does it obey business rules?
↓
Does it need normalization?
↓
Use / Store
And the four concepts become:
Type
→ Is it the right kind of value?
Syntax
→ Is it correctly formatted?
Semantics
→ Does it make sense?
Transformation
→ How should we represent it?
The most important distinction is probably this:
Validation should establish whether the input satisfies the contract. Transformation should deliberately establish the representation your application wants to work with.
What I Learned From This
The interesting part of backend development isn’t always the large architectural concepts.
Sometimes it’s understanding what happens to a tiny piece of data between:
“A user typed something into a form”
and:
“The database stored it.”
There are several decisions hidden in that journey:
What did the user send?
↓
Can we parse it?
↓
Is its structure correct?
↓
Are its types correct?
↓
Does the format make sense?
↓
Does the value make sense?
↓
Should it be normalized?
↓
Does the operation follow business rules?
↓
Can it safely be stored?
That’s a much more useful mental model than simply thinking:
“Add validation to the form.”
Going Deeper
I documented the full technical version separately, where I go deeper into:
- Runtime validation vs TypeScript types
- Schema-based validation
- Syntactic vs semantic validation
- Transformation and normalization
- Type coercion
- DTOs and internal representations
- Unknown fields
- Partial updates
- Cross-field validation
- Business rules
- Database constraints
- Race conditions
- Security boundaries
- Request pipelines
- Client-side vs server-side validation
If you’re learning backend development, the deeper version is where the topic starts becoming really useful from an engineering perspective.
Read the complete Developer View on my portfolio →
The browser can make suggestions.
The server makes the decision.
And the database protects the rules that absolutely cannot be broken.
메타데이터
- post_id
- f2113ecdd615
- slug
- your-application-shouldnt-trust-the-data-it-receives-f2113ecdd615
- url
- https://medium.com/@abhimanyug987/your-application-shouldnt-trust-the-data-it-receives-f2113ecdd615
- canonical_url
- https://medium.com/@abhimanyug987/your-application-shouldnt-trust-the-data-it-receives-f2113ecdd615
- author_url
- https://medium.com/@abhimanyug987
- status
- ok
- fetched_at
- 2026-09-12 14:57:28