Skip to content

Question codes are load-bearing

The question code (e.g. food2) is three things at once:

  1. the key its answer is stored under in every response,
  2. the name rule conditions use to reference it,
  3. your join key in whatever consumes the data downstream.

That’s why the editor makes you choose it explicitly (no auto-generated slugs) and why changing one is treated as a real decision, with an impact dialog, not a casual edit.

Codes must start with a letter, use only letters, digits, _ and -, and stay under 64 characters. They’re unique per questionnaire, case-sensitively.

When you rename a code, the editor shows every rule that references it and confirms:

The question code is the key in submitted data and in rules. Historical responses keep the old key; only the version pinned to each response makes them interpretable.

On confirm, every rule reference in the draft is updated atomically — you can’t end up with rules pointing at a name that no longer exists.

What does not change: historical responses keep the old key. Each response is pinned to the questionnaire version it was answered against, so old responses stay interpretable — a v1 response read against the v1 definition still lines up. But if your downstream pipeline joins on the code across versions, migrating historical data after a rename is your responsibility; nothing rewrites stored answers.

Deleting shows the same style of impact dialog: which rules reference the question, and what happens to them — the referencing conditions are removed, and any rule left with zero conditions fails open:

  • a visibility rule left empty → the element becomes always visible;
  • a requirement rule left empty → a question becomes always required, a step/tab stops cascading requirement.

Failing open is deliberate: a deleted question should never silently hide other content or leave requirements in an undefined state. Historical responses keep their submitted answers under the deleted code.

Deleting a step or tab aggregates the same analysis across everything inside it, and tells you how many tabs/questions are going before you confirm.

  • Name codes like durable identifiers, not labels: contactEmail, not q7 or Email (updated). You’ll read them in Mongo, CSV headers, and rule builders for the life of the questionnaire.
  • If a code must change after real responses exist, treat it like a schema migration: rename, publish, and update your downstream consumers — and remember the CSV export is per-version, so old exports keep old headers.