Do we still need DTO ?
Source: Dev.to

I recently had the pleasure of talking about DTOs with a fellow engineer. During our discussion, I destructured the API response directly from the backend in my frontend code. I immediately noticed the disappointed look on their face. That got me thinking: why do we even need DTOs in the first place?
What is a DTO?
A DTO (Data Transfer Object) is a structured object used to transfer data between layers or systems. It often exists to:
- Validate data coming from the backend.
- Transform backend responses to match frontend needs.
- Decouple frontend and backend schemas to avoid breaking changes.
In traditional REST APIs, DTOs are common because responses may include extra fields, nested structures, or data that the frontend doesn’t need.
How GraphQL Changes the Game
GraphQL allows the client to request exactly the data it needs. This has several implications:
- Fine‑grained queries – You define the shape of the data on the client‑side query, reducing the need for mapping large responses to a DTO.
- Strong typing – GraphQL schemas are strongly typed. Tools like Apollo Codegen or GraphQL Code Generator can automatically generate TypeScript types for your queries and mutations.
- Flexible frontend evolution – If the backend adds extra fields, your client won’t be affected unless you query them. DTOs no longer serve as a shield against breaking changes.
When You Might Still Want DTOs
Despite GraphQL’s strengths, there are cases where DTOs in the frontend can be useful:
- Business logic transformation – Compute new fields, format dates, or merge multiple queries into one object suitable for the UI.
- Validation or sanitization – Enforce stricter rules before the UI consumes optional or nullable fields from the backend.
- Decoupling for long‑lived projects – In large teams, a DTO can isolate frontend code from backend schema changes, especially when the backend is shared across multiple clients.
When You Probably Don’t Need DTOs
- Small apps or MVPs – The overhead of mapping to DTOs usually outweighs the benefits.
- Type‑safe GraphQL clients – If you’re using TypeScript with generated types, your types already act as a “live DTO.”
- Direct UI consumption – If your components can directly consume the GraphQL response, adding DTOs adds boilerplate without much gain.
Side note: Some still prefer to have DTOs as part of a clean architecture. What’s your perspective?