If you've been writing C# for more than a few years, you've written thousands of DTOs. Request models, response models, event payloads, integration contracts — the connective tissue of every distributed system. And if you're like most of us, you've written nearly all of them as classes with { get; set; } properties, because that's what we've done since .NET Framework 2.0.
Here's the uncomfortable truth: a mutable class is the wrong data structure for a DTO, and it has been since C# 9 gave us a better one. Not "stylistically wrong." Wrong in ways that show up as production incidents — duplicate payments, corrupted audit trails, and race conditions in async pipelines.
This article makes the case from first principles, with examples drawn from banking and fintech systems — payment processing, reconciliation, maker-checker workflows — because that's where the cost of getting this wrong is measured in money, not just bugs. Whether you're a junior engineer writing your first API co
Discussion
Say something first
It all starts with you—share your thoughts now.