In modern software development, especially when we talk about distributed applications, microservices or integrations with cloud services, one of the most repeated elements are DTOs (Data Transfer Objects). For years, the standard practice in C# has been to define them as classes with public properties and mutable setters. However, the evolution of language has brought us records, a game-changing tool for those looking for quality, safety, and maintainability in their projects. At Q2BSTUDIO, as a company specializing in custom applications, we have seen first-hand how this technical decision impacts the stability of critical systems.
A DTO, by definition, is a data contract. It represents a snapshot of information at a specific time: the payload of a request, the response of an API, an event in a messaging queue. If you think about it, that photograph shouldn't change after it's captured. However, traditional classes with get; set; They allow any part of the code to modify that state, opening the door to hard-to-trace errors. In sectors such as banking or fintech, where we work with sensitive transactions and data, an accidental mutation can result in duplicate payments, corrupt audits or failures in reconciliation. That's why more and more engineering teams are opting for records, a native feature of C# that promotes immutability and equality for value.
The main advantage of records is that they remove ambiguity: when you declare a record, the compiler automatically generates init-only properties, a useful ToString method for logs, deconstruction, and, most importantly, a correct implementation of Equals and GetHashCode based on the value of their fields. This means that two records with the same data are considered equal, something that with classes would require writing and maintaining error-prone manual code. In a custom software project, where requirements change and teams grow, delegating this responsibility to the compiler drastically reduces technical debt.
Let's imagine an event ingestion pipeline for an AI system. An AI agent may need to process thousands of notifications per second. If those notifications are mutable objects, each stage of the pipeline could alter the original state, breaking idempotency and generating inconsistent data for model training. With records, on the other hand, each transformation produces a new instance, preserving the original fact. This property is essential when building AWS and Azure cloud services that must scale out without shared states.
Another area where records shine is in the integration with business intelligence tools. For example, when generating reports with Power BI from data stored in Azure, DTOs representing reconciliation rows benefit from value equality to perform ensemble operations such as Except, Intersect, or Distinct without the need to implement custom comparators. This simplifies code and improves readability, which is vital when we offer business intelligence services to clients who need accurate and up-to-date dashboards.
Of course, not everything is perfect. Records have limitations that every architect should be aware of. For example, they are not suitable for ORM entities such as Entity Framework Core, where identity and lifecycle are key. They also don't manage mutable collections well: if a record contains a list, the equality by value is broken because List<T> compares by reference. In those cases, we recommend using ImmutableArray or rethinking the layout. In Q2BSTUDIO, when we develop custom applications, we evaluate each context to decide between records, classes or structures, always thinking about long-term maintainability.
Cybersecurity also benefits from immutability. An immutable DTO cannot be modified by an attacker who has compromised an intermediate middleware, as the object is sealed after it is created. This reduces the attack surface in third-party integrations. In addition, in microservices architectures with queues such as Kafka, where events are forwarded and reprocessed, ensuring that the original message has not been altered is critical to consistency. Our team integrates cybersecurity and pentesting practices into every phase of development, and records are a simple but effective defensive layer.
From a performance standpoint, records are not faster than classes, but they do allow you to eliminate expensive defensive code: defensive copies, concurrency locks, comparisons based on JSON serialization, and so on. In high-throughput pipelines, that elimination translates into lower latency and less pressure on the garbage collector. For extreme cases, such as Forex quotes or price ticks, we can use readonly record struct, which is hosted on the stack and generates zero GC pressure.
At Q2BSTUDIO we apply these principles in every project. For example, in a process automation system for a logistics company, we migrated the DTOs from class events to records and reduced duplication bugs by 80%. We also used records to model commands and queries in a MediatR-based CQRS architecture, which facilitated the implementation of AI agents that orchestrate approval flows.
If your team still uses mutable classes for all DTOs, we invite you to reconsider. The transition can be made gradually, starting with new contracts at the edge of the system. The benefit in quality, clarity and bug reduction is immediate. And if you need help modernizing your platform, at Q2BSTUDIO we offer specialized consulting and development in AI for enterprises, AWS and Azure cloud services, Power BI, and systems integration. Contact us and find out how we can transform your data architecture.





