Blog / 2026
Session replay for developers: what it is actually good for
Session replay has a positioning problem with engineers, and it is mostly the category’s own fault. The tools were built for conversion-rate optimisation, sold to marketing teams, and demoed with heatmaps. If your first exposure was a sales deck about funnel drop-off, “record every user’s screen” reads as something between snake oil and a liability.
It is a genuinely useful debugging tool anyway. Here is the developer case, including the parts that are not flattering.
What it does that your existing tools do not
You already have logs, error monitoring, and analytics. Replay covers a specific gap between them.
| Tool | Answers |
|---|---|
| Logs | What the server did |
| Error monitoring | Where the code threw, with a stack |
| Analytics | How many people did a thing |
| Session replay | What the user was doing when it went wrong |
The gap is client-side failures that never throw. A caught exception with an empty handler. A fetch that 422s and gets swallowed. A button whose click handler never bound because a script loaded out of order. A form that validates silently and refuses to submit with no message.
None of those produce a stack trace. None produce a log line. In analytics they appear as an unexplained dip. They are, in practice, the single largest category of “user reports something, developer cannot reproduce it”.
How it works
Every mainstream tool is built on the same idea, and most on the same library: rrweb. It serialises the DOM once as a full snapshot, then records a stream of mutations, mouse positions, scrolls, and input events. Playback re-applies those mutations into an iframe.
Two consequences follow.
It is not video. Nothing is screen-captured. Playback is a DOM reconstruction, which is why recordings are small, text stays selectable, and you can inspect elements during playback. It is also why replay breaks in ways video would not — canvas, WebGL, cross-origin iframes, and shadow DOM all need special handling and often degrade.
Fidelity depends on capture settings. If a tool did not record canvas, the canvas is blank on playback. If it masked inputs, fields show as filled but empty. These are choices with trade-offs, not bugs.
The performance question
This is the objection worth taking seriously, because the answer is not “zero”.
You are adding a script that observes DOM mutations and buffers serialized events. On a stable page that is negligible. On a page mutating thousands of nodes per second — a virtualised table, a canvas animation, a live-updating chart — the observer has real work to do.
What to check before adopting anything:
- Wire size of the tracker. UserTapes’ is under 15 KB, loaded
asyncfrom your own origin rather than a third-party CDN, so it is never in the critical path and never a third-party dependency in your hot path. - Whether payloads are compressed client-side. Uncompressed DOM event
streams are large. UserTapes gzips in the browser via
CompressionStream, typically 5–10× smaller. - Whether ingest triggers CORS preflight. A tool doing a preflight OPTIONS before every batch doubles its request count. Simple requests avoid it.
- What happens when the ingest endpoint is down. The buffer must be capped. A tool that grows an unbounded array while its API is unreachable will take your page down with it.
Ask vendors these four questions. The answers are diagnostic of how carefully the client was built, and a surprising number cannot answer them.
One more, which nobody advertises: ad blockers. A meaningful share of
visitors block analytics scripts, and filter lists match on URL patterns. If
the tool loads from a third-party domain, or serves a file with rrweb in the
path, expect silent gaps in your data. Serving from your own origin helps; it is
not a complete fix.
The privacy question
If you are the engineer, you are the one who ends up responsible for this, so it is worth being deliberate.
The failure mode is recording what people type. A tool that captures raw input values will eventually capture a password typed into a mislabelled field, or a card number, or someone’s medical history in a support form.
The only setting that really matters is whether masking happens at record time in the browser or server-side after upload. Server-side means the raw values crossed the network and landed in someone else’s infrastructure before being scrubbed.
UserTapes masks all inputs in the browser before transmission, with no allowlist and no per-field configuration to get wrong. That is a deliberate trade: you cannot debug a bug that depends on the exact string someone typed. Defaulting to safe is the right call, but it is a real limitation, and tools offering selective unmasking are both more useful and more dangerous.
The longer version, including where “cookieless” does and does not get you out of a consent banner, is in session replay and GDPR.
The workflow problem
Here is the thing that actually determines whether you keep using replay after week two.
The data is genuinely valuable. The interface is a video player. Those are incompatible. Nobody is going to watch 400 sessions to find the four that matter, and any tool whose answer to that is “we have filters” has understood half the problem.
Two things help. Filtering by signal — sessions containing an error, a rage cluster, a specific URL — narrows 400 to 12. And then not watching video at all: reading a text account of what happened instead.
- 0:19 click button "Apply coupon"
- ⚠ 0:20 POST https://example.com/api/coupon · 422
- ⚠ 0:23 rage click ×4 · button "Apply coupon"
That is faster to read than the recording is to load, and it is greppable. The player is still there when you want to see the moment, and the timestamps link into it.
It also means an agent can read it. Sessions exposed over MCP let Claude Code or Cursor query recordings alongside the code — see session replay over MCP.
When not to bother
You have no users yet. Replay tells you what people did. With five sessions a week you will learn more from talking to them.
Your bugs already produce stack traces. If error monitoring catches everything, replay adds context you may not need. Its value scales with how much of your logic is client-side and how much of it fails quietly.
Your app is mostly canvas or WebGL. DOM-based replay will show you very little.
You need aggregate analysis. “What is the conversion rate of this funnel” is a question for an analytics tool with a query engine. Replay answers questions about individual sessions well and aggregate questions shallowly.
You cannot commit to the privacy work. If nobody will own masking configuration and retention policy, do not turn it on. This is one of the few tools where a careless setup is worse than no tool at all.
Choosing one
For a developer specifically, the criteria that matter:
- Masking at record time, on by default
- Tracker size, and whether it is served from your own origin
- Retention you control
- An API or protocol rather than only a dashboard — you will want this by month two
- Pricing that does not assume a marketing budget
That last one eliminates a surprising number of options. Several of the best replay tools are priced for teams with a CRO department, which is a poor fit for one developer who wants to know why checkout broke for eleven people on Tuesday.
UserTapes is built for that case: cookieless, masked at the source, under 15 KB, with a text transcript for every session and MCP access on every plan including the free one — 100 sessions, no card, no expiry. Related: how to reproduce a bug a user reported and what is a rage click.