Relationship: Self
Written later and filed to this date, as part of filling in every day of the year.
The repository was created on a Friday night at a quarter to ten, from the framework’s starter template. Twenty-four minutes later the first database migration was stamped. By half past one the next afternoon there were five, and the first real commit, the one with ninety files and twelve thousand lines in it, would not arrive until Sunday. The whole shape of the product was decided in the gap between the template and the commit, and the schema is the only record of it.
Five migrations
The first migration is the product as conceived. A user, a subscription, an interview session, a question template, a question-and-answer pair, a personality profile, and a log of every call to the model. One user, one profile. The specification, committed on Sunday alongside the code, still describes it this way: the archive owner is “the primary user who signs up, pays, and creates their personality archive”. You are interviewed about your own life. You review the profile the model writes of you. Later, someone talks to it.
The second migration, an hour later, adds chat sessions and messages: the talking-to-it part. The third adds a table of standard questions and the usage tracking for tiers, because the tier that pays nothing gets no generated questions and needs forty-eight pre-written ones instead. The fourth, around lunchtime, adds a pending question. Four migrations, one idea, each a room added to the same house.
The fifth is a different house. It creates a table called Archive, with a name whose comment reads “Name of the person being archived”, and a relationship whose comment gives the examples: “Self”, “Mother”, “Grandfather”, “Friend”. It adds an archiveId to the interview session, the profile and the chat session, so every piece of data that used to hang off a user now hangs off an archive. And it creates ArchiveSlotPurchase, a record of paying for the right to hold one more.
Who the person was
Until half past one on Saturday the person being archived and the person paying were the same row. After it they were different tables, joined by a relationship column whose very first example value, “Self”, is there to cover the old case as a special case of the new one.
Read that way, the fifth migration is the moment the product found out what it was for. An app that interviews you about your life is a diary with a better interface. An app that interviews your mother, or your grandfather, and keeps a voice the grandchildren can ask questions of, is the sentence in the README: an archive “for future generations”. The data model got there on Saturday afternoon. The specification, written for the single-row version, never did, and was committed the next day as if nothing had changed.
The script
There is one more file in that first commit that only makes sense in this light: a migration script, separate from the schema migrations, whose header says it associates “all existing Q&A pairs with the ‘Founder’ archive”. It looks up the archive named Founder, fails loudly if there is none, and moves every interview session and profile that has no archive, or a different one, under it.
A script to move existing answers means there were existing answers. Someone had been interviewed, on Friday night or Saturday morning, under the first schema, before the idea of an archive existed, and when the fifth migration arrived those answers needed an owner. The only archive there was got the name Founder, which is as close as a schema comes to saying who sat for the first interview. Whatever the product was going to be for other people, the first relationship on record was the one the column’s comment lists first.
What it taught
The second day of this repository has its own story, three services blowing up the same way at build time. This is about the first day, and the lesson is quieter. A product’s real design decision often happens before the first commit, in a place the commit history cannot see, and the schema migrations are frequently the only timestamped witness. Read them in order and they are a diary of the idea changing its mind.
The other lesson is in the specification, which was wrong on the day it was committed and still is. Nothing in the pipeline compares a spec to a schema. The migration names did the work of documenting the pivot, and did it better, because a migration cannot describe a table it did not create.
The column is still there. Its first example is still “Self”.