ENGINEERING INSIGHTS · PRODUCT ENGINEERING
Build for the next release. And the one after.
How product engineering teams make each release answer a question: release briefs with decision rules, thin vertical slices, flags that separate deploying from releasing, and stable rollouts.
01 / 06
The first release is an instrument
The first version of a feature is a bet placed with incomplete information. Its job is to deliver value, and also to tell the team which of its assumptions were wrong. A release that cannot answer that question has spent the team's time and taught it nothing.
That changes what "building it well" means. A well-built early release is one that can be measured, changed, or removed cheaply. Architecture still matters, but it serves a specific goal: keeping the ability to respond to what the team learns without turning each change into a rewrite.
02 / 06
Write down the question before the code
Before building, write a short release brief. It is a page, not a document, and it forces the conversation that usually happens too late: what would make us keep this, change it, or remove it?
release: bulk-import-v1
question: >
Do new workspaces with existing data activate faster
when they can import it instead of entering it by hand?
leading_metric: share of new workspaces with 10+ records within 48 hours
guardrails:
- support tickets tagged "import" per 100 imports
- p95 import duration for files under 10 MB
audience: new workspaces, 50% rollout, assignment stable per workspace
decision_rules:
keep: leading metric improves for the import group and guardrails hold
rework: imports are started but rarely completed
remove: no measurable difference after four weeks at full rollout
flag: bulk_import # default off; doubles as the kill switchTwo parts do most of the work. The guardrails name what must not get worse, so that a feature that lifts one number by breaking another is caught. The decision rules are written before any data exists, which keeps everyone honest when results arrive and someone is attached to the outcome. Teresa Torres's opportunity solution trees are a useful way to connect each release question to the outcome it serves.
03 / 06
Slice vertically, and thinly
A thin vertical slice delivers one narrow path through every layer (interface, logic, and data) to real users. A horizontal slice delivers one layer completely: the whole import data model, then the whole parser, then the interface. Horizontal slices feel efficient and are not. Nothing reaches a user until the last layer lands, and by then the earlier layers encode assumptions nobody has tested.
For bulk import, the first slice might accept only CSV, for one record type, with fixed column mapping, listing errors rather than fixing them in place. That is enough to answer the brief's question. Excel files, custom mapping, and inline correction are the next slices, and the data may show that some of them are unnecessary. Basecamp's Shape Up describes the same instinct as fixing the time and varying the scope.
- 01Question
Release brief: leading metric, guardrails, decision rules
- 02Thin slice
One narrow path, end to end, to real users
- 03Flagged release
Deployed dark, then enabled for a stable cohort
Guardrail breached: flag off in seconds
- 04Measure
Leading metric and guardrails, per cohort
- 05Decide
Keep, rework, or remove, by the rules written first
Remove: delete the code and the flag
04 / 06
Separate deploying from releasing
Feature flags let code reach production before users see it. That separation is what makes small, frequent deploys safe for a team working on one main branch, a practice DORA describes as trunk-based development, and it is what makes a percentage rollout possible. Pete Hodgson's taxonomy of feature toggles separates release, experiment, ops, and permissioning toggles. They have different lifetimes and owners, and mixing them up is how flag systems become unmanageable.
For rollouts and experiments, assignment must be stable: the same workspace should see the same variant on every request and every server, or the measurements mean nothing. Hashing the flag name with the subject's ID gives deterministic bucketing without storing any assignments:
import { createHash } from "node:crypto";
/** Deterministic: the same flag and subject always land in the same bucket. */
export function inRollout(flag: string, subjectId: string, percent: number): boolean {
const digest = createHash("sha256").update(`${flag}:${subjectId}`).digest();
const bucket = digest.readUInt32BE(0) / 2 ** 32; // uniform in [0, 1)
return bucket < percent / 100;
}
// Raising the percentage only adds subjects; nobody already included is removed.
const enabled = inRollout("bulk_import", workspace.id, 50);Including the flag name in the hash matters. Without it, the same workspaces would fall into the first 10% of every rollout and become the permanent test group for everything. Bucket by the unit you analyze, too: if the metric is per workspace, bucket by workspace, not by user, or members of one team will see different products.
05 / 06
Keep the code as changeable as the plan
The engineering habits that support this are not exotic. Keep domain logic separate from delivery details, so the import rules can be tested without a browser and reused when the API needs them. Make interfaces explicit where there is a real boundary, and resist layers for requirements that have not arrived. Write the tests that let you change code with confidence, starting with the logic most likely to change.
Then clean up. Give every release flag a removal date when it is created. A flag that has sat at 100% for a month is dead code with a configuration switch attached, and every one left in place doubles the paths someone has to reason about. Deleting code is part of finishing a release, not a separate chore.
06 / 06
Before the next release
- Is there a written question, a leading metric, guardrails, and decision rules?
- Is the first slice thin enough to ship in days and still answer the question?
- Is it behind a flag with a kill switch, with assignment stable per unit of analysis?
- Can the team see the metrics per cohort without filing a data request?
- Does the flag have a removal date?
Five yes answers do not guarantee a good feature. They guarantee that the team will find out quickly, and cheaply, whether it has one. That is the way we run custom software development engagements.
References
- Feature Toggles (aka Feature Flags) Pete Hodgson, martinfowler.com
Toggle categories, lifetimes, and implementation techniques.
- Opportunity Solution Trees Teresa Torres, Product Talk
Connecting outcomes, opportunities, and the experiments that test them.
- Trunk-based development DORA
Research on small batches and short-lived branches as a delivery capability.
- Shape Up Ryan Singer, Basecamp
Fixed time, variable scope: shaping and slicing product work.
HOW NEURALSHARKS CAN HELP
Related NeuralSharks services
- Engineering
Custom software development
Software shaped around your users, operations, and ambitions.
- Product discovery and technical architecture
- Application and backend development
- Release planning and ongoing evolution
- Engineering
Web development
Fast, accessible web experiences built for real use.
- Information architecture and interface development
- Responsive applications and content systems
- Performance and accessibility checks
- Engineering
Mobile app development
Useful mobile products from first interaction to daily habit.
- Mobile product and experience planning
- Application development and backend integration
- Device testing and release preparation
- Quality
Software testing
Understand product risk before your users encounter it.
- Risk assessment and test planning
- Functional and exploratory testing
- Defect analysis and release reporting
- Quality
Test automation
Reliable feedback for every meaningful change.
- Automation strategy and framework setup
- API and critical journey test suites
- Pipeline integration and test maintenance