← Build log

Don't Break What You Love: The Art of Adding Features to Perfect Software

December 15, 2024

There’s a moment every product manager dreads—it usually happens right after you’ve built something beautiful, something that works exactly as intended, something your users genuinely love. That moment when someone (often yourself) says: “You know what this needs? More features.”

It’s like looking at a perfectly prepared steak and thinking, “This could really use some ketchup.”

The Perfect Product Dilemma

I was staring at VoiceCatcher’s settings panel the other day—all clean lines and elegant sliders, working exactly as designed—when I realized I needed to fundamentally expand what it could do. We had this beautiful, simple voice-to-text app that our users adored for its simplicity and reliability. But there was a problem: it maxed out at 5-second recordings.

Five seconds.

Try dictating your grocery list in five seconds. Try recording a meeting. Try capturing that brilliant idea that takes exactly 47 minutes to fully explain. You can’t. The tool we’d built for quick voice notes had natural expansion into long-form territory, but getting there without destroying what made it special? That’s the product management equivalent of performing surgery with a chainsaw.

TLDR: What You’ll Gain

  • A surgical approach to feature expansion that preserves core user experience
  • Progressive disclosure techniques that keep simple things simple
  • Feature flag strategies for risk-free rollouts
  • Real design patterns for mode-aware interfaces
  • Bottom Line Value: Learn how to add powerful capabilities without alienating users who love your current simplicity

The Surgical Approach

Here’s what I learned about adding features to software people already love: you don’t add features to software people already love. You add capabilities behind choices.

The difference matters. Features get shoved in your face. Capabilities wait patiently until you need them.

When we started designing long-form recording for VoiceCatcher, my first instinct was to replace the simple “Stop delay” slider with something more complex. Maybe a dropdown with “Quick,” “Medium,” and “Long” options. Maybe separate settings for different use cases. Maybe a modal dialog that asks what kind of recording you’re doing.

All terrible ideas.

Instead, we designed what I’m calling a “mode-aware interface”—a UI that transforms contextually based on user intent, rather than cramming everything together in visual chaos.

The Feature Flag Foundation

Before we touched a single pixel of the beloved interface, we built a foundation: an “Enable advanced recording modes” toggle, buried in settings, defaulted to OFF.

This isn’t just about A/B testing or gradual rollouts (though it enables both). It’s about respect. Respect for users who chose your app specifically because it doesn’t have the feature you’re about to add.

When that toggle is off, VoiceCatcher looks and behaves exactly as it always has. When it’s on, the interface reveals new capabilities in a way that feels natural, not bolted-on.

// The magic of conditional features
{settings.enableAdvancedRecordingModes && (
  <RecordingModeSelector />
)}

<RecordingControls
  mode={settings.enableAdvancedRecordingModes ? currentMode : 'quick'}
/>

Simple code, profound implications. Your existing users get exactly what they’ve always gotten. Your power users get capabilities they never knew they wanted.

Progressive Disclosure in Practice

Here’s where most product managers go wrong: they think progressive disclosure means hiding features behind clicks. It doesn’t. It means revealing complexity only when complexity is chosen.

Our solution was mode-specific panels that occupy the same visual space:

Quick Mode (Default): The exact current interface. Zero changes. If you never enable advanced modes, you never see any evidence they exist.

Long-Form Mode: Appears only when explicitly selected. Shows extended timeout sliders (10 minutes to 2 hours), chunking strategies, and session management options.

Manual Mode: Completely different paradigm—start/stop control with real-time processing options.

The genius is in the real estate. Instead of making the interface bigger to accommodate new features, we made it smarter. The same panel space shows different controls based on what you’re trying to accomplish.

It’s like having a Swiss Army knife where you only see the tool you need, not all 47 attachments at once.

The Tray Menu Challenge

But here’s where it gets interesting—the tray menu. This is where users actually initiate recording, so it has to reflect the new capabilities without confusing existing workflows.

Our approach: conditional complexity.

When advanced modes are disabled, the tray menu remains exactly as it is: “Start Recording.” One click, familiar behavior, zero confusion.

When advanced modes are enabled, “Start Recording” becomes “Recording Modes ▶” with a submenu for Quick, Long-form, and Manual options.

Same muscle memory for existing users. New capabilities for users who choose them.

Technical Architecture That Scales

The real challenge wasn’t UX—it was making this technically feasible. Long-form recording means dealing with memory management, chunking strategies, real-time processing, and session recovery. All things that could easily make the app slower, heavier, or less reliable.

Our solution was streaming chunked architecture: instead of recording one massive audio file, we process 30-60 second chunks in the background while recording continues. This keeps memory usage constant regardless of session length and enables real-time features like paragraph-by-paragraph transcription.

The key insight: the user doesn’t care about your technical architecture. They care about whether pressing the record button still works the same way it always has.

The Testing Integration Story

One thing I’m particularly proud of: we enhanced our existing audio testing dashboard to validate these new capabilities without disrupting our current test suite.

Long-form recording adds complexity: chunking strategies, memory management, session recovery, real-time processing. Each needs comprehensive testing, but not at the expense of our existing test coverage.

So we built it as an extension: new test categories for long-form capabilities, but the same test runner interface. You can run basic tests (current functionality) or enhanced tests (including long-form). The testing experience scales with the feature complexity.

What This Means for Solo Builders

If you’re building something people love, you’re going to face this dilemma. The temptation is real: add features to show progress, to justify continued development, to chase new user segments.

Resist.

Instead, think in terms of expansion packs for your core experience. Your app should work perfectly for its primary use case, then offer optional expansions for users who need more.

The framework:

  1. Feature Flag Everything: New capabilities should be opt-in, not forced upgrades
  2. Preserve Core Workflows: The primary user journey should remain unchanged
  3. Design for Context: Don’t add complexity; add contextual intelligence
  4. Test Progressively: Validate new capabilities without disrupting existing reliability
  5. Respect User Choice: Some users chose your app specifically because it doesn’t do what you’re about to add

The Business Reality

Here’s the thing: this approach is harder to build but easier to sell. When users opt into complexity, they’re making an informed choice. They understand they’re trading simplicity for capability, and they’re grateful for the option rather than resentful of the imposition.

Contrast this with the traditional approach: add features for all users, document the hell out of them, and wonder why your NPS scores are dropping despite “obvious improvements.”

Users don’t want better software. They want software that better serves their specific needs without getting in the way of workflows they’ve already mastered.

The Long Game

Six months from now, I suspect most VoiceCatcher users won’t even know the long-form capabilities exist. They’ll continue using it exactly as they always have: quick voice notes, elegant simplicity, zero friction.

But the users who need to record 2-hour presentations? They’ll have that capability, cleanly integrated, thoroughly tested, and elegantly presented.

That’s not just good product management—it’s respect for the users who trusted you enough to love your software in the first place.

Takeaways for Technical Product Managers

Copy-Paste Framework for Feature Expansion:

  1. Build the feature flag first - before any UI work
  2. Design mode-aware interfaces - same space, different controls
  3. Preserve existing workflows - zero disruption to current users
  4. Test capabilities independently - don’t break existing test coverage
  5. Document the choice - help users understand what they’re opting into

Decision Tree: Should This Be a New Feature?

  • Will this fundamentally change how current users experience the app? → Feature flag it
  • Does this serve the same core use case in a different context? → Mode-aware design
  • Would any current user be confused by this addition? → Progressive disclosure
  • Can I implement this without touching existing code paths? → Probably the right approach

The hardest part about building software people love isn’t the initial creation—it’s the discipline to keep loving it yourself, even when you see opportunities for “improvement.”

Sometimes the best thing you can add to perfect software is the choice not to experience your additions.

Bottom Line: Don’t break what users love in service of what they might want. Build expansion packs, not replacements.


Jeremy builds VoiceCatcher, a privacy-focused voice-to-text app that proves you can add sophisticated capabilities without sacrificing elegant simplicity. When he’s not overthinking product decisions, he’s probably dictating grocery lists in exactly 4.7 seconds.