Storage and your data

Recordings are plain gzipped JSON files in your bucket. Everything else is in a handful of database tables. Both are yours to back up, export or delete.

Object storage

S3 has no append operation, so every upload from the recorder becomes its own object:

Key Contents
sessions/<session>/parts/<first-timestamp>-<page>-<seq>.json.gz One batch of events, gzipped

If you set S3_PREFIX, it is added in front of every key. A batch the recorder retried overwrites the same object.

Database

D1 and Postgres use the same schema:

Table Contents
sessions One row per session: start, end, duration, first and last URL, page views, user agent, device, viewport, and counts of events, clicks, rage clicks, errors and inputs
session_pages One row per page view: session, time, host, path and full URL
session_users The user IDs attached to each session
batches One row per uploaded batch, used to ignore retries and to detect rage clicks that span two batches
settings The admin password hash and cookie signing secret

Exporting

There is no lock-in format. To export a session, copy its folder under sessions/ from the bucket and its rows from the database. To export everything, back up the bucket and the database with the tools you already use.

Deleting

Delete a session from the dashboard or with DELETE /api/sessions/:id. This removes its recordings and its rows. There is no automatic retention limit yet; to keep only recent data, use your bucket’s lifecycle rules together with a scheduled query that removes old rows.