DEV Community

Alexander Kazanski
Alexander Kazanski

Posted on

The Privacy Bug in Your Health App Isn't a Bug. It's the Architecture.

In fintech, engineers get trained early to treat every field as a potential liability. Health app teams, especially small ones, often don't get the same instinct — until a support ticket makes it clear that a symptom log or weight entry was sitting somewhere it shouldn't. The fix usually isn't a patch. It's a different default at the architecture level.

Stop passing raw health objects through your component tree

A common anti-pattern: fetch the full user health record once, then pass it down through five layers of props so every component can grab what it needs.

// Fragile: every child has access to everything, including fields it doesn't need
<Dashboard user={fullHealthRecord} />
Enter fullscreen mode Exit fullscreen mode

Instead, shape data at the boundary, before it enters your component tree:

function toDashboardView(record) {
  return {
    displayName: record.name,
    recentWeight: record.weightLog.at(-1)?.value,
    streakDays: record.streak,
    // deliberately excluded: medications, diagnosis notes, full history
  };
}
Enter fullscreen mode Exit fullscreen mode
<Dashboard view={toDashboardView(fullHealthRecord)} />
Enter fullscreen mode Exit fullscreen mode

This is more files, more mapping functions, more code to review. What you get is a system where a component literally cannot leak a field it was never given — no audit needed, because the shape of the data enforces the boundary.

Logging is where this usually goes wrong

It's common to log a whole state object during debugging and forget to strip it before shipping:

// Don't do this in a health app
console.log("user state:", userState);
Enter fullscreen mode Exit fullscreen mode

A small habit that pays for itself: build a logSafe wrapper that only logs an explicit allowlist of fields, and make it the only logging path your team uses for anything touching user state.

The honest tradeoff

Field-level data shaping adds friction to fast iteration — every new feature needs its view function updated, and that's real velocity cost early on. But the alternative is discovering, after launch, that a third-party analytics call accidentally captured someone's medication list. In this domain, the architecture is the privacy policy. Everything else is just paperwork describing it.

Top comments (0)