---
title: "Make data objects immutable · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/data-shapes/immutable-data
updated: 2026-10-20
licence: "All rights reserved"
---

# Make data objects immutable

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Recommended
- Chapter: [Data shapes](https://agentwranglers.se/playbook/architecture/data-shapes)
- Rule: Make DTOs and value objects read-only. Create a new object for a change instead of editing one that others may hold.
- How: Use `readonly` classes or properties, frozen dataclasses or `Readonly` types. Add `with` methods that return a changed copy when needed.
- Check: The type checker rejects writes to fields. Examples are TypeScript `readonly`, PHP `readonly`, and Python `@dataclass(frozen=True)`.

Example:

```ts
// Bad: anyone holding the order can change its total
class Order { total = 0; }

// Good: changes make a new object
class Order {
  constructor(readonly total: number) {}
  withTotal(total: number): Order { return new Order(total); }
}
```

```python
@dataclass(frozen=True)
class Order:
    total: int

changed = dataclasses.replace(order, total=120)
```

```php
final readonly class Order
{
    public function __construct(public int $total) {}
    public function withTotal(int $total): self { return new self($total); }
}
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/data-shapes/immutable-data`.

- Previous: [Parse input once at the boundary](https://agentwranglers.se/playbook/architecture/data-shapes/parse-at-the-boundary)
- Next: [Model each state as its own type](https://agentwranglers.se/playbook/architecture/data-shapes/states-as-types)
- [Data shapes](https://agentwranglers.se/playbook/architecture/data-shapes)
