Form Responses as Institutional Memory: Designing the Record Layer" FORMLOVA has designed a response schema that preserves field identity and respondent context long after the original form is retired, using two-level identity and label snapshots to ensure historical queries remain legible. The schema stores stable field IDs, semantic names, and submission-time label snapshots alongside each response value, allowing teams to reconstruct the exact question asked even after field renames, form deletions, or product-line restructuring. This approach, implemented across 29 field types, prioritizes long-term institutional memory over the short-lived form definition, solving the common problem of response data becoming opaque as forms evolve. Most form schemas I have seen were designed for the wrong time horizon. They were designed for the moment of submission. A responses table that captures field values. A foreign key to a forms table. A few denormalized columns for created time, IP, and user agent. Maybe an is test flag added later because someone needed it. This is fine if the only thing you ever do with a response is fire a webhook and forget. It is not fine if the team is still going to be reading those responses five years later. This article is about how to design the record layer of a form product so it remains useful long after the form itself has been retired. I will use FORMLOVA https://formlova.com/en as the working example, because it is the codebase I work in. The patterns themselves are not FORMLOVA-specific, but the concrete examples are pulled directly from FORMLOVA's response schema and from the MCP tool surface that operates on it 129 tools across 25 categories, including a dedicated response-management category whose only job is to keep the record honest over time . Every form product has the same structural asymmetry. forms lifetime ~ weeks to months responses lifetime ~ years The form is the intake surface. It changes when the campaign changes, the legal text changes, the product line shifts, the team rotates. Six months is a long life for a single form. The responses live in the database long after the form has been deleted or archived. The team will still query them at quarter end, at compliance review, at customer success post-mortems, at year-three product reviews. This means the response schema has to survive things the form does not. It has to survive field renames. It has to survive form deletions. It has to survive ownership handoffs. It has to survive product-line restructuring. It has to survive your own future schema changes. That is a much harder design problem than "store the submission." The most common source of long-term pain is field identity that was never designed to be stable. A response stores {"field 3": "Acme Co."} . Six months later, field 3 has been renamed to field 7 because the form was reordered. The original meaning is now lost unless you can reconstruct it from a Git history nobody reads. Two-level identity solves this. type FieldDescriptor = { // Stable across the life of the response. Never recycled. stableId: string; // Semantic name reused across forms. e.g. "company", "consent marketing". semanticName: string; // Position-only id used for current rendering. renderId: string; label: { default: string; locales?: Record