HIPAA-friendly error tracking: what the law actually requires

BAA, masking, audit logs, retention. A non-lawyer's guide to what you have to do, and what your error tracker has to do for you.

·
privacyhipaacompliance

It's 2 AM, a production bug is spiking, and you're digging through stack traces to find the root cause. You find it: a null pointer in the patient_record object. But as you scroll through the breadcrumbs, you realize you're looking at a patient's full name, date of birth, and ICD-10 diagnosis codes—all sent in plain text to your error tracker. In the eyes of the law, you haven't just found a bug; you've potentially initiated a reportable data breach.

HIPAA compliance in error tracking gets treated as a legal checkbox, something the procurement team handles by collecting a signed PDF. But for the engineers actually shipping the code, it is an architecture problem. The acronyms—PHI, BAA, RBAC—all map to concrete decisions about how your SDK is configured, what your ingest pipeline strips, and who can open a replay. This post skips the legalese and explains what HIPAA-compliant error tracking actually requires you to build.

HIPAA 101 for Developers: Covered Entities vs. Business Associates

HIPAA divides the world into two roles that matter here. A Covered Entity is the healthcare provider, health plan, or clearinghouse—the organization that has a direct relationship with the patient. A Business Associate is any vendor that handles Protected Health Information (PHI) on the Covered Entity's behalf. If your app serves a clinic and your error tracker ingests a stack trace containing a patient's name, that error tracker just became a Business Associate, whether anyone signed paperwork or not.

Why "the cloud" doesn't exempt you from responsibility

There's a persistent myth that pushing data to a SaaS vendor offloads the compliance burden. It does not. The Covered Entity remains liable for every downstream system that touches PHI. If you, the developer, pipe diagnosis codes into a tool that has no Business Associate Agreement in place, the liability flows straight back up. "We didn't know the SDK captured that" is not a defense the Office for Civil Rights accepts.

The 18 identifiers: what counts as PHI in a stack trace

HHS defines eighteen categories of identifiers that, when tied to health information, become PHI. The trap for engineers is that error data is dense with them. A stack trace, a breadcrumb trail, or a captured request body can quietly carry several at once:

  • Names — serialized into a logged user object or a page title.
  • Dates (birth, admission, discharge) — passed as form fields in a captured POST body.
  • IP addresses — collected automatically by most SDKs from request headers.
  • Device identifiers and serial numbers — attached as tags or context.
  • URLs — a route like /patients/12345/labs?mrn=A8842 embeds a record locator.
  • Account numbers and medical record numbers — the most direct leak, often sitting in query strings.

The lesson: PHI in error tracking is almost never a single labeled "PHI" field. It is contextual data that becomes regulated the moment it sits next to a health fact. The same problem shows up under European law—our companion post on GDPR error tracking blind spots walks through where contextual PII hides for non-healthcare apps.

The Business Associate Agreement: Your "License to Log"

A Business Associate Agreement (BAA) is the contract that makes it lawful for a vendor to process PHI on your behalf. It defines what the vendor may do with the data, requires safeguards, and obligates breach notification. If you are building a healthcare app, you cannot send PHI to a tool that won't sign one. Full stop.

What a BAA guarantees, and what it doesn't

A BAA establishes that the vendor will protect the data, restrict access, and report incidents. What it absolutely does not do is absolve you of sloppy logging. A signed BAA covering your error tracker does not make it acceptable to dump a full patient chart into a breadcrumb. The agreement governs the vendor's handling of data that legitimately needs to be there; it is not a blanket permission slip to capture everything. Minimum-necessary data collection is still your obligation as the engineer writing the capture logic.

Why many "free" tiers are off-limits for healthcare

This is the part that surprises teams. Most error trackers—Sentry, Rollbar, Bugsnag—only offer a BAA on their enterprise or business-tier plans, never on self-serve or free tiers. So the moment a developer spins up a free project to track errors in a healthcare-facing feature and PHI flows in, the organization is out of compliance regardless of how careful the code is. Before you point any SDK at production health data, confirm a BAA is actually executed and covers that specific plan.

Client-Side Masking: Stopping PHI at the Source

The single most effective HIPAA control is architectural: never let PHI leave the browser or the server in the first place. If the data never reaches the ingest endpoint, there is no breach to report and no retention window to worry about. Every major SDK exposes hooks for exactly this.

Using beforeSend and beforeBreadcrumb to scrub

The beforeSend hook runs on every event before it is transmitted. beforeBreadcrumb runs on every breadcrumb before it is attached. Together they are your last line of defense at the edge of the client.

Blacklisting vs. whitelisting

Most teams reach for a blacklist—a list of bad keys like ssn and email to strip. This is the wrong default for HIPAA. A blacklist fails open: any field a developer forgets to add, or a new field a future feature introduces, sails straight through. The only safe strategy is an allowlist—explicitly name the handful of keys that are safe to send, and drop everything else. It fails closed. A new diagnosis_notes field that nobody anticipated is silently removed instead of silently leaked.

// Allowlist scrubbing: only known-safe keys survive.
const SAFE_KEYS = new Set(["user_id", "route", "status_code", "build"]);

function scrub(value) {
  if (Array.isArray(value)) return value.map(scrub);
  if (value && typeof value === "object") {
    const out = {};
    for (const [k, v] of Object.entries(value)) {
      out[k] = SAFE_KEYS.has(k) ? scrub(v) : "[redacted]";
    }
    return out;
  }
  return value;
}

Sentry.init({
  dsn: process.env.GLITCHREPLAY_DSN,
  beforeSend(event) {
    if (event.extra) event.extra = scrub(event.extra);
    if (event.request?.data) event.request.data = scrub(event.request.data);
    return event;
  },
});

Server-Side Scrubbing and PII Rules

Client-side masking is necessary but not sufficient. Leakage happens—a new endpoint, a refactor, a developer who logged the whole object "just to debug." You need a second, server-side line of defense that runs on ingest regardless of what the SDK did.

Regex-based scrubbing as a backstop

Pattern-based rules catch structured identifiers that slip past key-name matching. Social Security numbers (\d3-\d2-\d4), credit card numbers via a Luhn-aware pattern, and date-of-birth formats can all be redacted by value, not just by field name. This matters because the data you didn't expect—a free-text note field, a concatenated log line—is exactly where regex rules earn their keep. GlitchReplay's ingest applies server-side PII rules on every event, and you can preview how a rule behaves against sample payloads with the PII scrubbing tester.

The human-error factor

Picture a new hire debugging a checkout flow. They write logger.error("failed for", user) instead of user.id. That one line ships the entire database row—name, address, insurance ID—into every error for that path. No client allowlist on that particular call site catches it because the developer bypassed the wrapper. Server-side scrubbing rules that run on every ingested event are the only thing standing between that mistake and a breach notification.

The Session Replay Elephant in the Room

Session replay is the highest-risk surface in your entire observability stack, because it captures the UI—and the UI is exactly where PHI is rendered for humans to read. A replay of a patient portal can show a full chart on screen.

Masking vs. blocking

There is a critical difference between masking (replacing visible text with asterisks while keeping the element's shape and layout) and blocking (removing the element from the recording entirely). For form inputs, masking usually suffices. For an entire chart panel, you want blocking so that not even the structure of the data hints at its contents. The underlying engine behind most replay tools, rrweb, supports both via CSS classes and configuration.

Strict privacy modes: mask by default

Compliance-by-design means your replay configuration should default to mask all text and inputs, then selectively unmask the handful of elements you've confirmed are safe (a status badge, a non-PHI button label). The inverse—recording everything and masking the sensitive bits—is the same fail-open trap as a blacklist. When auditing a replay tool for healthcare use, check for: TLS in transit, encryption at rest, role-restricted access to recordings, and configurable retention. GlitchReplay's replay defaults to masking inputs; see the security documentation for the full posture.

Access Control and Audit Logs: Who Watches the Watchmen?

HIPAA requires that you can answer the question "who accessed this patient's data, and when?" for every system in scope—including the error tracker.

RBAC and the death of shared logins

Role-Based Access Control means a junior contractor debugging the frontend should not be able to open a replay containing a psychiatric intake form. Roles scope who sees what. And the corollary: shared logins are a HIPAA violation, plain and simple. A team@company.com account that five engineers use makes the audit log useless—you can never attribute access to an individual. Every person needs their own identity.

Retention as a liability, not a feature

Vendors love to advertise long retention windows. For healthcare, keeping error logs full of PHI for five years is a liability, not a benefit—it's five years of breach exposure for data you stopped needing after a sprint. Short, deliberate retention with configurable windows is the compliant posture. Keep what you need to debug, then let it expire.

Flat-Rate vs. Per-Event Pricing in Healthcare

Healthcare apps often need high-volume, complete event capture for auditability. That collides badly with per-event pricing models.

Why sampling is dangerous for HIPAA audits

To control costs under per-event billing, teams turn on sampling—keeping, say, 10% of events. But if an incident triggers a breach investigation, the 90% you discarded might have contained the evidence of when and how the exposure happened. You can't reconstruct an audit trail from sampled data. Cost-driven sampling and complete auditability are in direct tension.

Flat-rate capture without a compliance tax

This is where flat-rate pricing changes the calculus. When the bill doesn't scale with volume, there's no financial pressure to sample out the very data your auditors need. GlitchReplay is Sentry-SDK compatible, applies strict server-side PII scrubbing by default, gives you configurable retention and role-based access, and charges a flat rate so 100% capture never produces a surprise invoice. We publish our data-processing terms at /dpa and document our privacy posture at /privacy.

HIPAA-friendly error tracking isn't a single certification you buy; it's an architecture you build—allowlist scrubbing at the client, regex backstops on the server, mask-by-default replay, individual access with audit logs, and retention you actually control. Get those pillars right and your 2 AM debugging session never turns into a breach report.

Stop watching your error bill spike.

GlitchReplay is Sentry-SDK compatible, includes session replay and security signals, and never charges per event. Free to start, five minutes to first event.