C.W.K.
Stream
Lesson 01 of 04 · published

One Field Would Have to Lie

~11 min · two-truths, sentinel-dates, column-overloading, data-loss

Level 0Cold Hearth
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"When a crumb was written and which day it belongs to are two different truths."

Two Questions, One Field Can't Answer Both

Every crumb answers two questions about time. When was this actually written? — an objective fact the device knows the instant you tap. And which day does this belong to? — a judgment you make, which may be today, last Tuesday, or a day next month. These are genuinely different questions, and a single date field can only hold one answer. Whichever one you store, the field is now lying about the other.

Store the write-moment and you can't backdate: a memory that belongs to last week is stuck showing this week. Store the target day and you've destroyed the real write-moment: a crumb you scattered to March now claims it was written in March, and the honest record of when you actually thought it is simply gone. There is no clever single value that escapes this — the two truths are independent, so they need two fields. Vesta names them captured_at (immutable, device-set) and target_date (author-assigned, the only mutable date).

Never overload one column with two meanings. When a field is quietly asked to represent two independent facts, it will corrupt one of them the first time they disagree. The fix is not a smarter encoding — it's a second column. Two honest fields always beat one overloaded field pretending to be enough.

The Sentinel-Date Disease

Watch what happens to teams that collapse the two anyway. The single date field can't express 'no particular target day', so someone invents a sentinel — a magic value that means 'undated' or 'unknown': the Unix epoch, a far-future year 9999, a NULL that half the queries forget to handle. Then those sentinels leak. They sort to the top or bottom of every list, they slip past date-range filters, they show up as 'January 1, 1970' in the UI, and every downstream query grows a special case to dodge them. The sentinel is the scar tissue of a collapsed model — proof that one field was carrying two jobs and buckled.

Vesta never needs a sentinel, and that's the tell that the model is right. Every crumb has a real captured_at (it was written at some actual moment) and a real target_date (the author put it on some day). Neither is ever 'unknown', so there's no magic value to invent, no special case to remember, nothing to leak.

Code

One overloaded field vs two honest fields·python
# COLLAPSED — one field forced to serve two masters
crumb = {"date": "2026-03-14"}   # ...but which truth is this?
#   is it when I wrote it, or the day it's about?  You can't tell.
#   backdate a memory -> the real write-time is gone
#   and 'undated' needs a sentinel -> hello, 1970-01-01 in the UI

# TWO TRUTHS — each question keeps its own field
crumb = {
    "captured_at": "2026-07-24T09:15Z",  # immutable: when I wrote it
    "target_date": "2026-03-14",         # assigned: the day it's about
}
# both always real, never 'unknown' -> no sentinel, no special case

External links

Exercise

Find a field in a schema you know that quietly carries two meanings — a 'status' that's sometimes a state and sometimes a reason, a 'date' that's sometimes created and sometimes due, a nullable column whose NULL means three different things. Write out the two (or three) independent questions it's really answering, then split it into that many honest fields. Notice which sentinel value disappears.
Hint
The giveaway is a magic value or an overloaded NULL: if the field needs a special placeholder to mean 'none of the above', it's probably answering more than one question. Each real question deserves its own column that is always, honestly filled.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.