The most definitive form of data portability is to host the entire platform yourself. PostHog’s code is open-source, meaning you are not obligated to use their cloud. You can deploy the entire platform—including session replay—on your own infrastructure.
GDPR Article 17 ("Right to Erasure") requires you to delete user data upon request.
return element;
Before diving into the how , it is essential to understand the what . PostHog, inspired by , serializes the DOM and user interactions into a structured, non-video format. Instead of capturing pixel-heavy video files, it records incremental JSON snapshots—a lightweight and highly queryable data format. This commitment to data portability is also evident in PostHog's open-source foundation and its transparent pricing, which includes a generous free tier. The goal is to give you maximum visibility and control over your most valuable asset: your user data. posthog session replay portable
// session-recorder.ts interface SessionEvent type: string; timestamp: number; data: any;
PostHog keeps your recent sessions hot for analysis. But what about sessions from 18 months ago? You might not need to watch them, but legal compliance might require you to retain them.
The Session Recordings API allows for programmatic retrieval of recording data for custom storage or integration into external tools like support ticket systems. The most definitive form of data portability is
Point your PostHog JS SDK to your custom host: javascript
private openIndexedDB(): Promise<IDBDatabase> return new Promise((resolve, reject) => const request = indexedDB.open('SessionRecorder', 1);
recording = ph.session_recording.get('SESSION_ID') GDPR Article 17 ("Right to Erasure") requires you
But what does "Portable Session Replay" actually mean? And why does it matter more than navigator.sendBeacon ?
private handleMouseMove = (event: MouseEvent): void => // Throttle mousemove events if (this.shouldThrottle('mousemove', 50)) return;
logTypes.forEach(type => console[type] = (...args: any[]) => this.addEvent('console', type, args: this.sanitizeConsoleArgs(args), ); originalConsole[type].apply(console, args); ; );