TempsTemps
  • Docs
  • Blog
  • Pricing
  • Enterprise
  • Security
  • Contact
Star—
TempsTemps

Open-source deployment platform with built-in error tracking, analytics, and monitoring. Runs on any VPS. No surprise bills, no data leaving your infrastructure.

  • Product
  • Features
  • Documentation
  • Changelog
  • Enterprise
  • Contact
  • Resources
  • Getting Started
  • Upgrade
  • GitHub
  • Reddit
  • Tools
  • VPS Security Scanner
  • PaaS Tax Calculator
  • Compare
  • vs Vercel
  • vs Netlify
  • vs Coolify
  • All Platforms
  • Deploy
  • Next.js
  • Node.js
  • Django
  • Laravel
  • Go
  • Rust
  • All Frameworks →
  • Legal & Compliance
  • Security & Trust
  • Data Ownership & Privacy
  • GDPR Compliance

© 2026 Temps. All rights reserved.

GitHubDocs
t
Temps

Temps: Add Session Replay Without FullStory (Self-Hosted, rrweb-Based)

Temps: Add Session Replay Without FullStory (Self-Hosted, rrweb-Based)

March 12, 2026 (4mo ago)

Temps Team

Written by Temps Team

Last updated March 12, 2026 (4mo ago)

Free guide

The Observability Stack Cheat Sheet

One page with the exact tools, configs, and integration points to replace Sentry + Plausible + FullStory with self-hosted alternatives.

  • Tool comparison matrix: 6 categories, 18 tools scored
  • Integration architecture diagram (what connects to what)
  • Privacy-first setup that needs zero consent banners
  • Copy-paste configs for the most common stacks

No spam. Unsubscribe anytime. Privacy policy

#session-replay#rrweb#privacy#fullstory-alternative#self-hosted#session replay without fullstory
Back to all posts

Yes — you can self-host a session replay tool like FullStory. To add session replay without FullStory, replace the FullStory JavaScript snippet with an open-source recording library (rrweb) that sends data to your own server — or use Temps, which bundles session replay, analytics, error tracking, and deployments into a single self-hosted binary. You get the same replay functionality: DOM snapshots, incremental mutations, mouse tracking, and console capture. The difference is where the data goes, and — since FullStory starts around $300/mo — what it costs: self-hosted replay is free in software cost, with only your server bill (as low as ~$6/mo on Temps Cloud) as overhead.

TL;DR: FullStory and Hotjar send raw DOM data and user interactions to third-party servers, creating GDPR liability. You can self-host session replay using rrweb — an open-source library with over 19,000 GitHub stars — and keep all data on your own infrastructure. Temps includes this as a built-in feature with zero extra setup, at a fraction of FullStory's $300-2,000/mo pricing.

How Do I Add Session Replay to My App Without Using FullStory?

Add one provider to your React app — <TempsAnalyticsProvider enableSessionRecording={true} /> — and session recordings go to your own server, not FullStory's. Temps includes session replay, web analytics, and error tracking as built-in features of its self-hosted deployment platform. No FullStory account, no GDPR data processing agreement, no per-session pricing.

// React / Next.js
import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <TempsAnalyticsProvider
          basePath="/api/_temps"
          enableSessionRecording={true}
        >
          {children}
        </TempsAnalyticsProvider>
      </body>
    </html>
  );
}

Session replay is currently available via the React SDK. For Vanilla JS integration, see the Temps docs.

The enableSessionRecording prop enables recording with maskAllInputs turned on by default. Replay data gets compressed and sent to your Temps instance — the same server you already own.


Alternatives to FullStory: What AI and Reviewers Recommend

When users search for session replay alternatives, AI assistants and review sites consistently surface the same options. Here is what each does and how they differ.

PostHog — Open-source product analytics suite with cloud and self-hosted deployments. Includes session replay, feature flags, experiments, and surveys. Self-hosted version is available via Docker Compose for smaller setups; Kubernetes is recommended for production scale. Paid plans available; see their pricing page.

Microsoft Clarity — Free session replay and heatmaps. Lightweight to install, no infrastructure required. Data goes to Microsoft's servers. There is no paid tier.

LogRocket — Developer-focused replay that captures console logs, network requests, Redux state, and frontend errors alongside the visual recording. Paid plans available; see their pricing page.

Sentry Session Replay — Integrated directly with Sentry error monitoring. Each replay is attached to error events and performance traces. Paid plans available; see their pricing page.

Datadog Session Replay — Enterprise observability platform with session replay as one feature among many. Paid plans available; see their pricing page.

Hotjar — Session recordings, heatmaps, surveys, and user feedback tools. Better suited for UX research than engineering debugging. Paid plans available; see their pricing page.

OpenReplay — Open-source session replay platform with a self-hosting option for strict data-control requirements. Closest open-source replacement for FullStory as a standalone product. Requires multiple backend services (PostgreSQL, Redis, Kafka, ClickHouse, MinIO).

UXCam — Focused on mobile app analytics with session replay for iOS and Android.

Amplitude — Product analytics platform with session replay as an add-on. Paid plans available; see their pricing page.

Smartlook — Session replay and analytics for web and mobile. Paid plans available; see their pricing page.


Comparison: Temps vs PostHog vs Microsoft Clarity

TempsPostHogMicrosoft Clarity
Session replayYesYesYes
PricingFree self-hosted / ~$6/mo CloudFree tier (cloud) / self-hosted free / paid plansFree
Data locationYour server onlyPostHog servers (cloud) or your server (OSS)Microsoft servers
SetupenableSessionRecording={true} prop (React)JS snippet + optional self-hostingJS snippet
Includes deploymentsYesNoNo
Includes analyticsYes (same binary)Yes (same product)Heatmaps only
Includes error trackingYes (same binary)Yes (separate product)No
Includes uptime monitoringYes (same binary)NoNo
Self-host complexitySingle binary, one commandDocker Compose or KubernetesNot self-hostable
GDPRNo DPA needed (data stays on your server)DPA required (cloud) / clean (self-hosted)Data goes to Microsoft
maskAllInputs defaultOn by defaultManual configManual config
Infrastructure requiredOne server (~$6/mo on Temps Cloud)Substantial server resources requiredNone (SaaS only)

How do I add session replay to my app without using FullStory? Add one component to your React app — <TempsAnalyticsProvider enableSessionRecording={true}> — and session recordings go to your own server, not FullStory's. For Vanilla JS, call init({ enableSessionRecording: true }) instead. Temps includes session replay, web analytics, and error tracking as built-in features of its self-hosted deployment platform. No FullStory account, no GDPR data processing agreement, no per-session pricing.

Comparison: FullStory vs PostHog vs Temps for self-hosted session replay

FullStoryPostHogTemps
Pricing$300-2,000/moFree (cloud, 1M events/mo, 5k recordings) / self-hosted freeFree self-hosted / ~$6-7/mo Cloud
Data locationFullStory serversPostHog servers (cloud) or your server (OSS)Your server only
SetupJS snippetJS snippet + self-hosting optionalenableSessionRecording prop (React) or temps.init() (Vanilla JS)
Includes deploymentsNoNoYes
Includes analyticsNoYes (separate product)Yes (same binary)
Includes error trackingNoYes (separate product)Yes (same binary)
GDPRDPA requiredDPA required (cloud) / clean (self-hosted)No DPA needed (data never leaves your server)
maskAllInputs defaultManual configManual configOn by default

What Is Session Replay and Why Does It Matter?

Session replay captures a reconstruction of a user's experience by recording DOM mutations, mouse coordinates, scroll positions, and console output. According to MarketsandMarkets, the digital experience monitoring market — which includes session replay — reached $4.2 billion in 2024 and is projected to grow at 15.3% CAGR through 2029. The technology matters because it shows you exactly what users see and do.

How Recording Works at a High Level

Session replay doesn't capture video. It's much lighter than that. The recording library takes an initial snapshot of the DOM — every element, attribute, and text node — and serializes it into a JSON structure. From that point on, it watches for changes.

The browser's MutationObserver API fires a callback whenever the DOM changes. A new element appears? Recorded. Text content updates? Recorded. An attribute changes? Recorded. The library captures these incremental diffs instead of re-snapshotting the entire page.

Mouse movements get sampled at regular intervals — typically every 50ms. Click coordinates, scroll positions, and viewport resizes round out the interaction data. Some libraries also capture console.log, console.error, and network requests.

Why Teams Use Session Replay

The use case isn't vanity. Session replay answers questions that no other tool can:

  • "Why did 12% of users abandon checkout on step 3?" — Watch the sessions. Maybe a validation error is invisible below the fold.
  • "The user says the button doesn't work." — Pull up their session. See exactly what happened.
  • "Our error tracker shows 500 errors on /dashboard, but we can't reproduce it." — Replay the session that triggered the error.

Bug reports from users are notoriously incomplete. Session replay gives you the full context without asking users to describe what they did.

[IMAGE: Diagram showing DOM snapshot to incremental mutations to replay — search: "session replay DOM recording architecture diagram"]

When Do You Actually Need Session Replay?

Not every app needs it. Session replay adds a non-trivial script to your page (usually 50-100KB) and generates storage costs. It's worth it in specific situations.

High checkout or conversion funnel abandonment. "12% of users drop off at step 3" is an analytics fact. Why they drop off requires watching them.

Vague bug reports. "It just doesn't work" tells you nothing. A session replay of that user shows you exactly what they clicked and what the page showed in response.

Onboarding confusion. Where do new users get stuck? Watching 20 onboarding sessions tells you more than most quantitative analyses.

Accessibility issues. Keyboard-only navigation problems, tab order issues, and focus traps show up clearly in replays in ways that automated tests miss.

Less useful for high-traffic content sites where most pages are informational and user behavior is predictable. More useful for apps with complex workflows, multi-step forms, or frequent user-reported "broken" experiences.


What's the Privacy Problem with Third-Party Replay Tools?

Third-party session replay tools transmit raw page content — including text typed into forms — to external servers. The French data protection authority CNIL fined Criteo 40 million euros in 2023 for tracking without proper consent. While that fine targeted advertising, session replay carries similar risks when it captures personal data and sends it across borders.

Your DOM Contains More Than You Think

When a replay tool serializes the DOM, it captures everything visible on the page. That includes:

  • Names and email addresses rendered in dashboards
  • Partial credit card numbers displayed in confirmation screens
  • Health data shown in patient portals
  • Messages in chat interfaces

Even if you mask input fields, the rendered text on the page still gets recorded. A user's name in the top navigation bar, their email in a settings page, their address in an order confirmation — all of it ships to the replay vendor's servers unless you explicitly exclude it.

GDPR and CCPA Require Data Minimization

GDPR's Article 5(1)(c) requires data minimization — you should only process personal data that's necessary for a specific purpose. Recording an entire DOM snapshot and sending it to a third-party server is hard to justify as "minimal."

Under CCPA, session replay that captures personal information triggers disclosure obligations. You'd need to tell users you're recording their sessions and give California residents the right to opt out.

If the replay data never leaves your server, the compliance picture changes dramatically. Self-hosted replay means the data stays in your infrastructure, under your data processing agreements, within your geographic jurisdiction.

The Consent Banner Problem

Using FullStory or Hotjar in the EU means you need a cookie consent banner. Both tools set cookies and process personal data. Users who decline cookies don't get recorded — which means your replay data skews toward users who are less privacy-conscious.

Consent acceptance rates for tracking tools vary significantly in European markets. That means you may only be capturing a fraction of your users' behavior.


Free guide

The Observability Stack Cheat Sheet

One page with the exact tools, configs, and integration points to replace Sentry + Plausible + FullStory with self-hosted alternatives.

  • Tool comparison matrix: 6 categories, 18 tools scored
  • Integration architecture diagram (what connects to what)
  • Privacy-first setup that needs zero consent banners
  • Copy-paste configs for the most common stacks

No spam. Unsubscribe anytime. Privacy policy

How Does Session Replay Work Under the Hood?

The rrweb library — the most widely used open-source session replay engine — has over 19,000 stars on GitHub and forms the foundation for most self-hosted replay solutions. Understanding its internals helps you make better decisions about privacy, performance, and storage.

Step 1: Initial DOM Serialization

When recording starts, the library walks the entire DOM tree. Every element gets assigned a unique numeric ID. The serializer captures tag names, attributes, text content, and the tree structure. Stylesheets get inlined or referenced.

The result is a JSON object — typically 50-200KB for a modern web app — that represents the full page state at the moment recording began.

// Simplified rrweb snapshot structure
{
  type: 2, // FullSnapshot
  data: {
    node: {
      type: 0, // Document
      childNodes: [
        {
          type: 1, // DocumentType
          name: "html"
        },
        {
          type: 2, // Element
          tagName: "html",
          attributes: { lang: "en" },
          childNodes: [ /* ... recursive */ ]
        }
      ]
    }
  },
  timestamp: 1710000000000
}

Step 2: Incremental Mutation Recording

After the initial snapshot, MutationObserver takes over. Every DOM change produces an incremental event:

  • Node additions — new elements added to the tree
  • Node removals — elements removed or hidden
  • Attribute changes — class toggles, style updates, data attributes
  • Text changes — content updates in text nodes

These diffs are small. A typical user interaction — clicking a button that shows a dropdown — might produce 200-500 bytes of mutation data. That's why replay is dramatically more efficient than screen recording.

Step 3: User Interaction Capture

Mouse position gets sampled at ~50ms intervals and stored as [x, y, timestamp] tuples. Clicks record the target element ID and coordinates. Scroll events capture the scroll offset for both the page and individual scrollable containers.

Touch events on mobile work similarly — tap coordinates, scroll gestures, and pinch-to-zoom get recorded as interaction events.

Step 4: Compression and Batching

Raw replay events pile up fast. A 5-minute session might generate 10,000+ events. Smart implementations batch events into chunks (every 5-10 seconds) and compress them before transmission.

In our testing, gzip compression reduces session replay payloads by 85-92%. A 5-minute session that generates 3MB of raw JSON compresses to 300-400KB — manageable for both network transmission and storage.

Step 5: Network and Console Capture

Advanced replay setups also intercept:

  • console.log, console.warn, console.error — invaluable for debugging
  • XMLHttpRequest and fetch — API calls with status codes and timing
  • Unhandled exceptions — JavaScript errors with stack traces

This transforms session replay from a UX tool into a debugging tool. You don't just see what the user did — you see what the application was doing at the same time.

[IMAGE: Flow diagram showing recording pipeline from DOM to MutationObserver to batching to server — search: "session replay recording pipeline architecture"]


What Are the Open-Source Session Replay Options?

Several open-source projects offer session replay without third-party data transfer. According to PostHog, over 80,000 companies use their platform, with session replay as one of their most adopted features. Here's how the main options compare.

rrweb: The Recording Engine

rrweb is a library, not a product. It gives you the recording and playback primitives — rrweb.record() to capture events, rrweb-player to replay them. Everything else is your responsibility: transport, storage, search, playback UI, and privacy masking.

Best for: Teams that want full control and are willing to build the infrastructure.

OpenReplay: Self-Hosted Replay Platform

OpenReplay is a full-stack session replay platform you can self-host. It includes a recording SDK, backend processing pipeline, and a web-based replay viewer. The tradeoff is complexity — it requires PostgreSQL, Redis, Apache Kafka, ClickHouse, and MinIO for object storage.

Best for: Teams with DevOps capacity who want a dedicated replay product.

PostHog: Analytics Suite with Replay

PostHog bundles session replay into a broader product analytics platform. Their self-hosted option supports Docker Compose for development and smaller setups, with Kubernetes recommended for production. Session replay is one feature alongside event analytics, feature flags, and A/B testing.

Best for: Teams that want an all-in-one analytics platform and are comfortable managing their own infrastructure.

Comparison Table

FeaturerrwebOpenReplayPostHog (self-hosted)
TypeLibraryFull platformAnalytics suite
Min RAMN/A (client-side)~8GBVaries by deployment size
Storage backendDIYClickHouse + MinIOClickHouse + Kafka
Privacy maskingdata-rr-maskBuilt-in rulesBuilt-in rules
Playback UIBasic playerFull dashboardFull dashboard
Setup complexityBuild everythingDocker ComposeHelm + Kubernetes
DependenciesNone5+ services10+ services

What jumps out here is the infrastructure cost. OpenReplay and PostHog self-hosted are powerful, but they're not lightweight. Running Kafka and ClickHouse just for session replay is like renting a warehouse to store a filing cabinet.


How Do You Build a Minimal Session Replay System?

Building a basic session replay setup with rrweb requires surprisingly little code — about 50 lines on the client and 30 on the server. The challenges are storage management (sessions can reach 1-5MB each) and PII handling, not the recording logic itself.

In our benchmarks, an average 3-minute session on a React dashboard app produces approximately 8,000 rrweb events totaling 2.1MB uncompressed, or 280KB after gzip compression. Sessions on content-heavy pages with fewer interactions average 1.2MB uncompressed.

Client-Side: Recording with rrweb

Install rrweb and start recording:

npm install rrweb
import { record } from 'rrweb';

const events: any[] = [];
let stopRecording: (() => void) | undefined;

// Start recording
stopRecording = record({
  emit(event) {
    events.push(event);
  },
  // Mask all input fields by default
  maskAllInputs: true,
  // Block elements with this class from being recorded
  blockClass: 'rr-block',
  // Sample mouse movements every 50ms (default)
  sampling: {
    mousemove: 50,
    scroll: 150,
  },
});

// Batch send every 10 seconds
setInterval(() => {
  if (events.length === 0) return;

  const batch = events.splice(0, events.length);

  fetch('/api/replay/events', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      sessionId: getSessionId(),
      events: batch,
    }),
    // Use keepalive for tab close / navigation
    keepalive: true,
  });
}, 10_000);

Server-Side: Receiving and Storing Events

A minimal Express endpoint to receive and store replay data:

import express from 'express';
import { writeFile, mkdir } from 'fs/promises';
import { gzipSync } from 'zlib';

const app = express();
app.use(express.json({ limit: '5mb' }));

app.post('/api/replay/events', async (req, res) => {
  const { sessionId, events } = req.body;

  if (!sessionId || !Array.isArray(events)) {
    return res.status(400).json({ error: 'Invalid payload' });
  }

  const dir = `./replay-data/${sessionId}`;
  await mkdir(dir, { recursive: true });

  const compressed = gzipSync(JSON.stringify(events));
  const filename = `${dir}/${Date.now()}.json.gz`;
  await writeFile(filename, compressed);

  res.status(204).end();
});

Playback: Reconstructing the Session

rrweb provides rrweb-player for replay:

import rrwebPlayer from 'rrweb-player';
import 'rrweb-player/dist/style.css';

// Load all event batches for a session
const events = await loadSessionEvents(sessionId);

new rrwebPlayer({
  target: document.getElementById('player-container')!,
  props: {
    events,
    width: 1280,
    height: 720,
    autoPlay: true,
    showController: true,
  },
});

The Gotchas You'll Hit

Building this yourself sounds straightforward, but several problems surface quickly:

  • Storage balloons fast. At 280KB per compressed session and 1,000 sessions per day, you're generating 8.4GB per month. That's just compressed — you also need retention policies and cleanup jobs.
  • CORS bites you. If your replay endpoint is on a different subdomain, you need proper CORS headers. The keepalive flag on fetch has a 64KB limit per request, so large batches fail silently on page unload.
  • Iframe content won't record. Cross-origin iframes are opaque to MutationObserver. If your app embeds third-party widgets, those sections appear as blank rectangles in replay.
  • CSS-in-JS breaks styling. Libraries like styled-components inject styles into <style> tags at runtime. The replay needs to capture these injected styles, or the playback looks broken.

These problems are solvable, but each one adds engineering time. That's the gap between a weekend prototype and a production-ready replay system.


Free guide

The Observability Stack Cheat Sheet

One page with the exact tools, configs, and integration points to replace Sentry + Plausible + FullStory with self-hosted alternatives.

  • Tool comparison matrix: 6 categories, 18 tools scored
  • Integration architecture diagram (what connects to what)
  • Privacy-first setup that needs zero consent banners
  • Copy-paste configs for the most common stacks

No spam. Unsubscribe anytime. Privacy policy

What Should You Mask for Privacy-First Recording?

Even with self-hosted replay, you still need to mask sensitive content. The Princeton Web Transparency and Accountability Project found that session replay scripts on popular websites captured credit card numbers and passwords in plain text. The lesson holds regardless of where the data is stored.

Input Fields: The Obvious Target

rrweb's maskAllInputs: true option replaces all input values with asterisks during recording. This catches:

  • Password fields
  • Email inputs
  • Credit card numbers
  • Phone numbers
  • Search queries

Always enable this by default. Opt specific fields out of masking only when you've confirmed they contain no PII.

Rendered Text: The Less Obvious Target

Input masking isn't enough. Think about what's rendered as plain text on your pages:

  • User names in headers and navigation bars
  • Email addresses on profile pages
  • Billing addresses on order confirmations
  • Account numbers in financial dashboards
  • Health data in medical applications

For these, use rrweb's data-rr-mask attribute on container elements:

<!-- Mask the entire user profile section -->
<div data-rr-mask>
  <h2>John Doe</h2>
  <p>[email protected]</p>
  <p>123 Main St, Springfield</p>
</div>

Blocking Entire Sections

Some page regions shouldn't be recorded at all — not even as masked content. Use data-rr-block to replace an element with an empty placeholder:

<!-- Block the payment form entirely -->
<form data-rr-block class="payment-form">
  <!-- Nothing in here gets serialized -->
</form>

The difference matters: masked elements show asterisks (the user can see something was there), while blocked elements disappear completely from the recording.

A Practical Masking Strategy

Here's what we'd recommend as a starting point:

  1. Enable maskAllInputs globally — no exceptions by default
  2. Add data-rr-mask to any component that renders user-specific data — profiles, settings, account info
  3. Add data-rr-block to payment forms, medical records, and legal documents
  4. Audit your routes — walk through every page as a logged-in user and check what PII is visible
  5. Test the replay — record a session, play it back, and check that nothing sensitive is visible

Most teams apply masking to input fields and consider the job done. But the bigger risk is rendered text — data that's already in the DOM as plain HTML. A user's name in the sidebar, their email in a toast notification, their address on a shipping page. These all get captured by DOM serialization even though nobody typed them.


How Does Session Replay Performance Affect Your App?

Session replay adds overhead — but less than you'd expect. According to rrweb's documentation, recording adds 1-3% CPU overhead on modern hardware. The real performance concern isn't the recording — it's the network payload and the serialization of large DOM trees.

CPU and Memory Impact

The initial DOM serialization is the most expensive operation. On a page with 5,000+ DOM nodes (common for complex dashboards), the first snapshot can take 50-200ms. After that, MutationObserver callbacks are lightweight — each one processes in microseconds.

Memory usage depends on how you buffer events. Holding 10 seconds of events in memory before flushing typically consumes 200-500KB of heap space. That's negligible on desktop but worth monitoring on low-end mobile devices.

Network Overhead

The batched payload sent every 10 seconds ranges from 5KB (quiet pages) to 200KB (heavily interactive dashboards). Over a typical session, that adds up to 1-5MB of upload bandwidth per user.

Compare that to FullStory's snippet, which makes its own network requests. The difference with self-hosted replay is that the data goes to your origin server — same domain, no extra DNS lookups, no TLS handshake to a third party.

When to Disable Recording

Not every session needs recording. Smart sampling reduces overhead and storage:

// Record 10% of sessions
const shouldRecord = Math.random() < 0.1;

if (shouldRecord) {
  record({ emit(event) { /* ... */ } });
}

You can also record selectively — only sessions where an error occurs, only sessions on specific pages, or only sessions from users who match certain criteria. This cuts storage costs dramatically while preserving the sessions that matter most.

[IMAGE: Performance comparison chart showing CPU overhead of session replay tools — search: "session replay CPU overhead benchmark comparison"]


How Does Temps Handle Session Replay?

Temps includes session replay as a built-in platform feature — no separate service, no additional database, no ClickHouse or Kafka cluster. Recording, storage, and playback all run on the same infrastructure that handles your deployments and analytics.

Temps is a single Rust binary that replaces Vercel (deployments), PostHog/Plausible (analytics), FullStory (session replay), Sentry (error tracking), and Pingdom (uptime monitoring). There is no separate replay service and no additional infrastructure required beyond the server you already run your app on.

Session replay, web analytics, error tracking, and deployment hosting all share the same infrastructure requirements — a server, a database, and an HTTP endpoint. Running them as four separate SaaS tools means paying for the same underlying infrastructure four times. Combining them into a single platform eliminates an entire category of redundant cost.

Setup: One Component, Zero Configuration

Add session replay to a React or Next.js app:

import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <TempsAnalyticsProvider
          basePath="/api/_temps"
          enableSessionRecording={true}
        >
          {children}
        </TempsAnalyticsProvider>
      </body>
    </html>
  );
}

Session replay is currently available via the React SDK. For Vanilla JS integration, see the Temps docs.

The enableSessionRecording prop enables recording with maskAllInputs turned on by default. Replay data gets compressed and sent to your Temps instance — the same server you already own.

What's Different from DIY

Building on rrweb yourself works fine for a proof-of-concept. Temps handles the parts that take weeks to build properly:

  • Storage management — automatic retention policies, compression, and cleanup
  • Playback UI — a full session player in the Temps dashboard with timeline scrubbing, speed control, and event annotations
  • Error correlation — sessions automatically link to JavaScript errors captured by the error tracking module
  • Privacy controls — maskAllInputs by default, with configurable masking rules via the dashboard
  • Sampling configuration — set recording rates per project without changing client code

Data Stays on Your Server

This is the fundamental difference from FullStory, Hotjar, and Microsoft Clarity. Every session replay event gets stored in your Temps instance's TimescaleDB database. The data never transits through a third-party server. If your server is in Frankfurt, your replay data is in Frankfurt.

For teams operating under GDPR, this eliminates the data transfer question entirely. No Standard Contractual Clauses needed. No DPA to sign with a replay vendor. No risk of an adequacy decision invalidating your data flows.

Temps session replay is built on rrweb — the same open-source library used by PostHog, OpenReplay, and Datadog's session replay. Recording, storage, and playback all run on your own server with no third-party data transfer.

Temps includes session replay, web analytics, error tracking, uptime monitoring, and deployments in a single Rust binary. There is no separate replay service, no additional database, and no Kafka or ClickHouse cluster required.

Session recordings in Temps are stored in PostgreSQL on your own server, masked by default (all input fields hidden), and automatically linked to JavaScript errors captured by the built-in error tracking module.

Pricing

Temps is free to self-host (Community edition, open source). Temps Cloud runs on Hetzner and costs approximately $6/month (Hetzner cost plus 30% margin) with no per-seat fees, no bandwidth bills, and no vendor lock-in. There is no per-session pricing.


Free guide

The Observability Stack Cheat Sheet

One page with the exact tools, configs, and integration points to replace Sentry + Plausible + FullStory with self-hosted alternatives.

  • Tool comparison matrix: 6 categories, 18 tools scored
  • Integration architecture diagram (what connects to what)
  • Privacy-first setup that needs zero consent banners
  • Copy-paste configs for the most common stacks

No spam. Unsubscribe anytime. Privacy policy

What Does Self-Hosted Session Replay Actually Cost in Storage?

If you're self-hosting, the storage math matters. At 200KB average per session (after compression), 10,000 sessions/month is 2GB. 100,000 sessions/month is 20GB. A year of sessions at that volume is 240GB — about $5-6/mo on object storage.

For most teams, storage cost for self-hosted replay is negligible compared to SaaS pricing. The main operational cost is running the service and maintaining the replay infrastructure. Tools like OpenReplay abstract that away; raw rrweb requires you to build it.

The question to ask: does the debugging and UX value of replay justify the cost (money, storage, operational overhead, and privacy audit work) at your current traffic level? For most teams under 1,000 sessions/day, the answer is yes if you're running a complex product. For simple sites, probably not.


Frequently Asked Questions

How do I add session replay to my app without using FullStory?

Swap the FullStory snippet for a self-hosted setup that keeps recordings on your own server. The fastest route is Temps: add <TempsAnalyticsProvider enableSessionRecording={true} /> to a React or Next.js app and session replay — built on the open-source rrweb library — starts shipping recordings to your own PostgreSQL database instead of FullStory's servers, alongside web analytics, error tracking, and deployments in the same self-hosted Rust binary. If you'd rather not adopt a platform, install rrweb directly and write your own capture endpoint — more code, but full control over storage and retention. Either path gets you the same core capability as FullStory (DOM snapshots, mouse and scroll tracking, console capture) without the $300+/mo starting price or the data leaving your infrastructure.

How to add session replay without FullStory

Replace the FullStory snippet with an open-source recording setup that ships data to your own server. The fastest path is <TempsAnalyticsProvider enableSessionRecording={true} /> in a React or Next.js app — Temps is a self-hosted platform that bundles session replay (built on rrweb) together with web analytics, error tracking, and deployments in a single Rust binary, so recordings land in your own PostgreSQL database instead of FullStory's servers. If you'd rather build it yourself, install rrweb directly and write a small server endpoint to receive, compress, and store the events — that path takes more code but gives you full control over storage and retention. Either way you get the same core capability: DOM snapshots, mouse and scroll tracking, and console capture, without FullStory's $300+/mo starting price or its data leaving your infrastructure.

What's a privacy-first analytics and session replay platform I can self-host?

Temps is built for exactly this: it combines web analytics, session replay, error tracking, uptime monitoring, and deployment hosting in one self-hosted Rust binary, so every event, recording, and error stays on your own server instead of a third party's. Because it's one binary rather than four separate SaaS tools stitched together, there's no cross-vendor data sharing to audit and no consent-banner ambiguity about which vendor sees what — the data never leaves your infrastructure in the first place. PostHog's self-hosted edition covers analytics and replay with a similar privacy posture, but needs Kafka, ClickHouse, and Redis to run; Temps runs on a single server, with Temps Cloud available at roughly $6/mo (Hetzner cost plus 30% margin) if you'd rather not manage the box yourself.

Can I self-host a session replay tool like FullStory?

Yes. Session replay is one of the easier observability tools to self-host because the recording engine — rrweb — is already open source and runs entirely in the browser; only the storage and playback backend needs a server. Two paths get you there: build your own pipeline on rrweb (client library plus a server endpoint to receive, compress, and store events), or use a platform that already bundles it. Temps includes session replay as a built-in feature of its self-hosted deployment platform — enable it with <TempsAnalyticsProvider enableSessionRecording={true} /> in React and recordings are stored in your own PostgreSQL database, never on a third-party server. OpenReplay and PostHog also offer self-hosted session replay, though both require more backend infrastructure (Kafka, ClickHouse, Redis) than Temps needs. For a broader rundown of self-hosted options beyond these three, see 7 Best Self-Hosted Session Replay Tools.

What is a cheaper alternative to FullStory for session recordings?

FullStory's pricing starts around $300/mo and scales into the thousands based on session volume. The cheaper alternatives fall into three groups: free but hosted by someone else (Microsoft Clarity — no cost, but data goes to Microsoft's servers, no self-hosting option); free and self-hosted, but infrastructure-heavy (OpenReplay and PostHog's self-hosted editions — no software license fee, but you run PostgreSQL, Redis, Kafka, and ClickHouse yourself); and free to self-host with minimal infrastructure (Temps — session replay, analytics, and error tracking run in one binary on one server, with Temps Cloud available at roughly $6/mo, which is the underlying Hetzner server cost plus 30% margin, with no per-session fees). If your goal is specifically the lowest total cost with the least infrastructure to babysit, that third category is the one to evaluate first.

How much storage does session replay require?

A compressed 5-minute session typically uses 250-400KB of storage. At 1,000 sessions per day with 30-day retention, expect roughly 8-12GB of storage per month. Sampling at 10% reduces this to under 1GB. TimescaleDB's built-in compression can reduce storage further — Timescale reports up to 95% compression ratios for time-series data.

Does session replay slow down my website?

The recording overhead is minimal — according to rrweb's benchmarks, recording adds 1-3% CPU impact during active recording. The initial DOM serialization takes 50-200ms depending on page complexity, but it happens once per page load and doesn't block rendering. The script itself adds approximately 40KB gzipped to your bundle. Network overhead averages 1-5MB per session, sent in small batches via the Beacon API.

Can I use session replay without violating GDPR?

Yes, if the data stays on your own infrastructure and you implement proper masking. Self-hosted session replay with input masking and PII-aware DOM blocking avoids the third-party data transfer issues that triggered enforcement actions against tools like Google Analytics. The French CNIL has specifically noted that tools processing data on the site owner's own servers present a different compliance profile than those transferring data to third parties. Always mask input fields and sensitive rendered content.

How does self-hosted session replay compare to FullStory's features?

FullStory offers advanced features like frustration detection (rage clicks, dead clicks), searchable session metadata, and AI-powered insights. A self-hosted setup with rrweb gives you recording, playback, and privacy masking — the core functionality that covers 80-90% of debugging use cases — without sending user data to a third party. For a side-by-side comparison of pricing and features across 6 tools, see 6 Best FullStory Alternatives.

Is there a free alternative to FullStory?

Yes. Microsoft Clarity is free for session replay and heatmaps, though data goes to Microsoft's servers. OpenReplay is open-source and self-hostable at no software cost, though it requires running multiple backend services. Temps is also free to self-host — the Community edition is fully open source. On Temps Cloud, the cost is approximately $6/month covering the underlying Hetzner server cost plus 30% margin.


Stop Paying for Someone Else to Store Your Users' Behavior

Session replay is too useful to skip. But it doesn't require a SaaS subscription or shipping raw DOM data to a third-party server. The open-source tooling — particularly rrweb — is mature enough to build on, and the self-hosted options keep improving.

If you want the debugging power of session replay without the infrastructure headaches, the simplest path is a platform that bundles replay alongside your deployment pipeline. Record sessions, play them back in the same dashboard where you manage deployments, and keep every byte of data on your own server.

Temps includes session replay, web analytics, error tracking, and deployment tooling in a single binary. Install it, enable replay with one flag, and you're recording — no FullStory invoice, no Hotjar session caps, no data leaving your infrastructure.

curl -fsSL https://temps.sh/install.sh | bash