Feature Design Lab
The fields to answer before writing code, each with a worked answer for the same running feature — and, more usefully, what actually goes wrong when the field is left blank. The template earns its place in that last column or not at all.
A template is only worth filling in if leaving a field blank has a cost you can point at afterwards. So read each prompt, answer it out loud for a feature you are actually building, and then open the worked answer to compare. The what happens if you skip it block stays visible on every field, because that is the argument for the field existing — not that a process document says so.
- 1Problem
What is the user or the business unable to do today, and what do they do instead? Not the solution — the situation that makes the solution worth building.
What happens if you skip itWithout it the feature is defined by its mechanism, so every subsequent question is answered by asking "what would a pause button do" rather than "what does the customer need". The characteristic outcome is a feature that is built exactly as specified and does not reduce churn, and no one can say whether it failed or was never aimed at the problem — because the problem was never written down to compare against. - 2Actors
Who can trigger this, on whose behalf, and what is each of them trusted to assert? Include the non-humans: schedulers, webhooks, importers, back-office tools.
What happens if you skip itThe rule gets enforced only on the path the author happened to be looking at. The quota is checked in the HTTP handler, and then the back-office tool, the importer and a retention job each pause subscriptions without it — so the invariant holds for customers who used the website and for nobody else. This is also where privilege bugs live: writing down that the webhook is trusted to report payment results and nothing else is what makes it obvious that it must not be allowed to set PAUSED. - 3Inputs
What comes in, in what units, and which values are impossible? Say which inputs are already validated by their type and which need a check.
What happens if you skip itEverything arrives as a string or a number and validation becomes ambient — done somewhere, by someone, probably. Two call sites then disagree about whether the value they hold has been checked, and the one that assumed it was is the bug. The specific version of this in billing is the untyped amount: a number that is sometimes cents and sometimes a decimal currency unit, which produces an error of a hundred times in the direction the customer notices. - 4Outputs
What does a caller get back on success, and what do they get on each expected failure? Which of those failures are part of the contract rather than exceptions?
What happens if you skip itExpected refusals get thrown as generic exceptions or returned as a bare false, so the caller cannot distinguish policy from breakage. The UI shows "something went wrong" for a customer who has simply used both of their pauses this year, support cannot reproduce it, and the metrics count a product limit as an error rate — which means the one number that would have told you the quota was set wrong is buried in noise. - 5Invariants
What must never stop being true, stated about the data rather than about a code path? For each one, name the single place that enforces it.
What happens if you skip itRules survive as conditionals scattered across the paths that happened to need them, which means they are true in some paths and not others — and the ones that are false are, by construction, the paths nobody was thinking about. The second cost arrives later: nobody can tell whether a given check is a rule or a defensive leftover, so nothing can be safely deleted and the conditionals accumulate forever. - 6State
What states can this thing be in, what causes each transition, and which transitions must not exist? Where does that state live?
What happens if you skip itThe lifecycle survives as a set of booleans — active, trialing, paused, cancelled — and the system acquires states that are combinations nobody defined. Paused and cancelled at once is not an error the code rejects; it is a row that exists, and every query then needs to know the precedence rules in someone's head. The next feature adds another flag, and the number of representable combinations doubles again. - 7Dependencies
What does this need from outside itself, in which direction, and which of those things change on someone else's schedule?
What happens if you skip itVolatile dependencies get called directly from the rule, and the rule becomes untestable without them — which in practice means the month-end and leap-day cases are never tested, because setting up the case requires a real clock. The second effect shows up when the provider is replaced: with the SDK called from inside the domain logic, the provider's vocabulary has spread into the rules, and swapping it is a rewrite of code that has nothing to do with payments. - 8Failure modes
What can fail, what does the system look like immediately after each failure, and what fails about your mitigation?
What happens if you skip itThe design covers the path where everything works, and the failure paths get invented under pressure by whoever is on call — usually as a retry, which is the one fix that turns a single failure into a repeated one when the operation is not idempotent. The subtler loss is that mitigations go unexamined: an outbox and a retry both introduce new failure modes of their own, and a design that never asked what its mitigation costs has simply moved the problem somewhere less visible. - 9Security
Where is the trust boundary, what is authorized at it, and what is the smallest authority each participant needs to do its job?
What happens if you skip itAuthorization is inherited from whatever the surrounding endpoint already checked, which is fine until the operation is reused by a second entry point that checked something else — the classic being an admin tool that authorizes "is an admin" without asking "of which organisation". Least privilege skipped shows up differently: the scheduler is given the same credentials as the application because that was easiest, so a bug in a background job can do anything a user can. - 10Observability
When this misbehaves in production at 3am, what does the on-call engineer read? Include the signals for things that silently did not happen.
What happens if you skip itOnly failures are instrumented, so the failures that consist of nothing happening are invisible: the scheduler stops firing, no exception is raised, no request errors, and the first report comes from finance a month later. The other half of the loss is diagnostic — without a stable id threaded through the log line, the event and the metric, every investigation begins by reconstructing which subscription the incident was about. - 11Migration
This ships into a running system with existing data and clients you do not control. What is the order of changes, and what is true in between?
What happens if you skip itThe change is designed as if it were a fresh install, and the deploy is the first time old and new code run against the same rows. The recurring version of this is a new enum value written before every reader can read it, which during a rolling release means half the fleet treats paused customers as active for the duration. The other recurring version is a compatibility branch that was never scheduled for removal and is now load-bearing, because two callers have come to depend on the old shape. - 12Tests
What is verified, at which boundary, and what does the suite stop being able to detect at each place you substitute a fake?
What happens if you skip itThe distribution happens by accident rather than by decision, and it always lands the same way — a few end-to-end tests, because they are what proves the demo works. They are slow, so the date-arithmetic cases nobody enjoys writing are skipped, and those are precisely the cases that fail in production. Writing this field down has a second effect worth more than the tests: if a rule turns out to have no fast home, that is the design telling you the rule is tangled with transport or storage, and it is cheaper to hear that now than after the code exists.