A copy looks harmless. It's usually invisible. It's almost always unnecessary.
Every time you copy data, you:
Burn CPU
Touch memory you didn't need to
Trash cache locality
Increase GC / allocation pressure
And worst of all:
You duplicate reality.
Why Copies Hurt More Than You Think
A single copy is cheap. A system full of them isn't.
They stack:
deserialise → copy
map → copy
transform → copy
serialise → copy
Now you're not processing data. You're moving it around repeatedly for no reason.
Boxing is the Same Smell
Boxing is just a sneaky copy with extra ceremony.
value → heap
metadata wrapped around it
GC now cares about it
You didn't just copy the value. You changed its lifetime and cost model.
Boxing is a copy that escaped into the heap.
The Rule of Thumb
Default stance: don't copy. Don't box. Don't allocate.
Only break that rule when:
You cross a boundary that requires it
You need isolation for correctness
You're deliberately trading memory for something measurable
If you can't explain the reason, it's probably a bug.
The Better Model
Operate on views, not values:
Spans. Slices. References.
Same data. Different lens. No duplication. No churn.
When Copies Are Legit
Be honest about the exceptions:
Crossing process / network boundaries
Immutable snapshots for safety
Escaping lifetime issues you can't otherwise control
But even then: make it explicit. Make it rare. Make it obvious in code.
The Pattern
Most systems copy because it's easy.
Better systems don't copy because they understand the cost.
Great systems make copying awkward on purpose.