The Surnames We Cut Off At Thirty Characters

by Serguey Shinder

The letter came back to us with a note written in the margin. Our customer had printed her surname in full, and underneath it she had written, politely, that this was the fourth time she had asked.

Her surname is thirty-four characters long. On every letter we had ever sent her it appeared as the first thirty, stopping in the middle of a syllable.

The column was defined as thirty characters. The form on the website allowed sixty, because somebody had copied a length from another field years earlier, and the database did not object to the longer value. It kept what fitted and discarded the rest, and it reported success. The row was written. The application logged nothing. Nowhere on the path from her keyboard to our storage did anything express the view that something had gone wrong.

I want to be exact about the consequence, because it is worse than an embarrassing letter. The original value was never held anywhere. There was no audit table with the full string in it, no request log that kept bodies, no backup taken before the truncation, because the truncation happened at the moment of writing. Something over eleven thousand records were affected across fourteen years, and for every one of them the only surviving copy of the correct value was in the customer's own head. We could not repair the data. We could only ask for it again, which is a letter nobody enjoys writing.

What made this possible was a setting. Our database had been running for years in a mode where a value too large for its column is quietly adjusted rather than refused, and that mode was the default when the server was installed in 2011. Nobody chose it. Nobody knew it was a choice. Every developer who has ever worked on that system, myself included, believed they were writing to a store that either accepted a value or rejected it, and we were all wrong in the same direction for the same reason, which is that the system never once told us otherwise.

Switching to strict behaviour took an afternoon and broke four places on the way, all of which had been losing something. The wider habit is the part I would keep. Any boundary a value crosses either refuses what it cannot hold or alters it, and if it alters it, the alteration is invisible by construction. So I now ask of every store, every parser, every encoder, what does this do when the input does not fit. Not what does it do when the input is wrong, which everybody tests. What does it do when the input is merely too big, too long, too precise, or slightly the wrong shape.

A system that never rejects anything is not tolerant. It is lossy, and it keeps the loss to itself.

– Serguey Asael Shinder

Leave a Reply