Session Replay for Debugging: The Missing Link in Observability
Stop guessing what users experienced. Watch their actual sessions, correlated with your backend traces and logs.
You've been there. A user reports a bug. "It just doesn't work," they say. You check the logs—nothing obvious. You search for traces—everything looks fine. You spend hours trying to reproduce the issue, only to give up in frustration.
What if you could simply watch what the user did? See their clicks, their scrolls, their confusion. And then instantly jump to the exact backend traces that occurred during that moment.
That's the power of session replay integrated into your observability stack.
The Gap in Traditional Observability
Traditional observability focuses on three pillars:
- Logs — What happened in your systems
- Metrics — How your systems are performing
- Traces — How requests flow through services
But there's a fourth dimension that's often overlooked: what did the user actually do?
Without this context, you're solving puzzles with missing pieces. You see the backend effects but not the frontend causes. You know something triggered an error, but not how the user got there.
What is Session Replay?
Session replay captures DOM mutations, mouse movements, clicks, scrolls, and network activity in the browser. It reconstructs the user's experience so you can watch their session as if you were looking over their shoulder.
Modern session replay is not screen recording. Instead of capturing video (which would be huge and privacy-invasive), it records structural changes to the page. This approach is:
- Lightweight — Minimal impact on page performance
- Privacy-first — Sensitive data can be automatically masked
- Searchable — Sessions are indexed by user ID, URL, errors, etc.
- Correlatable — Links directly to traces and logs via session ID
The Correlation Magic
The real power comes when session replay is correlated with your backend observability data. Here's how it works:
Every browser session gets a unique session ID. This ID is sent as a header with every API request, allowing your backend to tag traces and logs with the same session ID.
// Frontend: Attach session ID to all requests
const sessionId = sessionStorage.getItem('session_id')
|| crypto.randomUUID();
sessionStorage.setItem('session_id', sessionId);
fetch('/api/checkout', {
headers: {
'X-Session-ID': sessionId
}
});
# Backend: Extract session ID and add to span
from opentelemetry import trace
@app.middleware("http")
async def add_session_context(request, call_next):
session_id = request.headers.get('X-Session-ID')
span = trace.get_current_span()
if session_id and span.is_recording():
span.set_attribute('session.id', session_id)
return await call_next(request)
Now when you're looking at a trace in your observability platform, you can instantly jump to the session replay. And vice versa—when watching a replay, you can see the exact traces that occurred.
Real-World Debugging Scenarios
Scenario 1: The Invisible Error
A user reports: "I clicked submit but nothing happened."
Without session replay, you might check:
- Server logs — No errors found
- Backend traces — No failed requests
- Frontend error tracking — No JavaScript exceptions
With session replay, you can see that the user clicked the submit button, but a validation error appeared in a toast that disappeared after 2 seconds. The form never actually submitted because of client-side validation.
Time to resolution: 2 minutes instead of 2 hours.
Scenario 2: The Race Condition
Intermittent 500 errors on the checkout page. Can't reproduce locally.
Session replay shows that the user rapidly double-clicked the "Place Order" button. Your backend wasn't idempotent, leading to a race condition.
You can even see the exact timing—the second click happened 150ms after the first.
Scenario 3: The Mobile Safari Edge Case
Users on iOS report the page "freezes." Your metrics show normal response times.
Session replay reveals that a CSS animation is causing layout thrashing on Safari Mobile. The page isn't frozen—it's just very slow, and users give up before it completes.
Implementation Best Practices
1. Privacy by Default
Always mask sensitive inputs by default. Credit cards, passwords, and personal information should never be captured:
<!-- Automatically masked by default -->
<input type="password" />
<input type="email" />
<input data-private="true" />
<!-- Entire sections can be blocked -->
<div class="qorrelate-block">
Sensitive content here won't be captured
</div>
2. Sampling for High-Traffic Sites
For sites with millions of users, capture 100% of sessions that:
- Encounter errors
- Trigger support tickets
- Match specific user segments
And sample a percentage of normal sessions for general insights.
3. Retention Policies
Session replays can be large. Set retention policies based on:
- Normal sessions: 7-14 days
- Sessions with errors: 30-90 days
- Sessions linked to support tickets: Until ticket closed + 30 days
Integration with OpenTelemetry
Modern session replay tools integrate natively with OpenTelemetry. The session ID becomes just another attribute in your telemetry data:
# OpenTelemetry Collector config
processors:
attributes:
actions:
- key: session.id
from_context: http.request.header.x-session-id
action: insert
This means your existing queries work seamlessly:
-- Find all traces for a specific session
SELECT *
FROM traces
WHERE attributes['session.id'] = 'abc-123-xyz'
ORDER BY start_time;
The ROI of Session Replay
Teams that implement session replay report:
- 60% faster mean time to resolution for frontend issues
- 40% reduction in "cannot reproduce" bug tickets
- Better collaboration between frontend and backend teams
- Improved UX insights beyond just bug fixing
Getting Started
Adding session replay to your observability stack is straightforward. With Qorrelate, it's a single script tag:
<script
src="https://qorrelate.io/replay.js"
data-org-id="YOUR_ORG_ID"
data-privacy-mode="mask-inputs"
></script>
Sessions are automatically correlated with your traces and logs via the session ID header.
Qorrelate includes session replay with full OpenTelemetry correlation at no extra cost. Start with our free tier and see the difference integrated observability makes.
Conclusion
Session replay isn't just another tool—it's the missing context that makes your existing observability data actionable. When you can see what users did, correlate it with what your backend did, and understand why things went wrong, debugging becomes dramatically faster.
Stop guessing. Start seeing.