Case Study 04

When restraint becomes the feature.

The feature was built. It was working. And the best decision was to wait.

Product strategy · Analytics · Constraint-led design

Practice cadence preset selection screen showing six scheduling options

Key decisions

Instrument before feature Privacy reframed the solution Signal defined before build Constraint led to better design The component was already waiting
Section:

The case study

It looked done.

A scheduling system. Six presets. A selection screen with icons and descriptions and a frequency badge that appeared in the user's profile. The UI was complete, the interaction was clean, and users could tap any preset and see it reflected in their profile.

Nothing else happened.

No reminder fired. No nudge appeared. No part of the app changed its behavior based on what the user had selected. The label implied a contract. The app never signed it.

A fully designed selection screen. Six presets. A profile badge. And nothing that connected any of it to actual behavior.
A fully designed selection screen. Six presets. A profile badge. And nothing that connected any of it to actual behavior.

The obvious fix wasn't the right fix.

The instinct is immediate: add reminders. Schedule notifications. Collect an email address and send a weekly nudge. It's what every other app does.

This product doesn't have email addresses. By design. The privacy architecture — no accounts, no server, no data transmitted — isn't a gap or a limitation. It's a promise. The community this product is built for is technically sophisticated and privacy-conscious. They chose this product partly because it doesn't ask for anything. Breaking that promise to add a scheduling feature would be a poor trade.

So the question shifted. Not how do we add reminders — but what does accountability look like when you can't contact the user?

That's a more interesting question. And it led somewhere better.

But first — does anyone care?

Before designing a solution, there was a more fundamental question to answer.

Practice scheduling is a Layer 2 feature. It only matters after a user has practiced enough to want to optimize their schedule. At early beta, users are still finding their footing with the core learning loop. They haven't been in the product long enough to feel the absence of scheduling guidance.

Building a complete accountability system for a feature that might be invisible to users is waste. The right move was to find out if it mattered before building anything.

The event was wired. The data wasn't there. Which meant either nobody was changing their preset — or the signal was being lost.
The event was wired. The data wasn't there. Which meant either nobody was changing their preset — or the signal was being lost.

The instrument before the feature.

Diagnosing the silence revealed a second problem. The analytics platform being used silently discards custom event properties on the current subscription tier. An event tracking preset changes was firing correctly — but the data attached to it was being dropped before it could be recorded.

The same was true for five other event types across the product. Input device mode. Practice category. Training level. Content preset. All firing. All dimensionless.

The fix was architectural and economical: encode the dimension directly into the event name.

Instead of passing properties that would be discarded, the dimension becomes part of the name. Two sibling events fire alongside the original. Full signal. No plan upgrade required. Historical continuity preserved.

Instead of passing properties that would be discarded, the dimension becomes part of the name. Two events. Full signal. No plan upgrade required.
Instead of passing properties that would be discarded, the dimension becomes part of the name. Two events. Full signal. No plan upgrade required.

What the signal will say.

With the instrumentation in place, the data will answer a specific question: are users engaging with the scheduling feature at all?

If the event never fires — if every user stays on the default preset — the feature is invisible. It may need repositioning. It may need to be removed. It may need to surface earlier in the experience.

If it fires consistently, the next question answers itself: which presets do users move to? That distribution reveals which scheduling concepts resonate with real learners — not assumed personas, but the actual people using the product.

The build decision waits for that answer.

After instrumentation. The signal is now detectable. The feature earns its build when users ask for it with their behavior.
After instrumentation. The signal is now detectable. The feature earns its build when users ask for it with their behavior.

The designed solution — ready when the signal arrives.

When the data says build, the implementation is already scoped. The solution is deliberately matched to what the architecture actually supports.

Session logging — after each practice session, the date, duration, and active preset are written to local storage. No server. No PII. Just enough to know when someone last practiced and whether that matches their stated intention.

The on-open nudge — at app launch, the last session date is compared to the preset's frequency expectation. If the user is overdue, a contextual suggestion surfaces. If they're on track, nothing appears. The component that displays this already exists — it just needs the logic layer connected.

PWA browser notifications — the product is a Progressive Web App. The browser's notification system can schedule reminders from the device itself, with no server required. The user opts in. The reminder fires locally. Nothing leaves the device.

The component was already built. Phase 1 connects it to real session data. The nudge appears when it's earned — not on every launch.
The component was already built. Phase 1 connects it to real session data. The nudge appears when it's earned — not on every launch.

What this case study is really about.

There's a version of every product where every feature gets built as soon as it's imagined. This isn't that product.

The scheduling feature existed as UI for months before this work began. It could have been wired to a backend. Reminders could have been added. The feature could have been declared done.

Instead: the instrumentation was built. The signal was defined. The build trigger was written down. And the feature waits — not because it isn't worth building, but because the product deserves to know it's needed before spending the effort.

That discipline — building the instrument before the feature, waiting for behavioral evidence before writing code — is harder than it sounds when you're the person who designed the UI and wants to see it come alive.

It's also the difference between a product that grows with its users and one that accumulates features they never asked for.

The build trigger is documented. When the signal arrives, the feature is ready. Until then, the instrument does the work.
The build trigger is documented. When the signal arrives, the feature is ready. Until then, the instrument does the work.


When restraint becomes the feature — the product earns the trust to build what users actually need.

View branded case study

This version is presented without product identifiers.

Incorrect code — get in touch to request access.