Skip to Content
FeaturesData Retention

Data Retention

Heartbeet automatically deletes old event data to manage database storage and respect plan limits.

Retention windows

PlanEvent retention
Free30 days
Starter1 year (365 days)
Pro3 years (1,095 days)
Enterprise3 years (1,095 days)

How it works

The cron job (/api/cron/analyze) runs a cleanup function at the start of each hourly run. It calls the cleanup_old_beet_events() PostgreSQL function, which deletes events from beet_events where received_at is older than the organisation’s retention window.

-- Simplified version of the cleanup logic delete from beet_events e using beets b join projects p on p.id = b.project_id join organizations o on o.id = p.org_id where e.beet_id = b.id and e.received_at < now() - ( case o.plan when 'free' then interval '30 days' when 'starter' then interval '365 days' else interval '1095 days' end );

Baseline data

Baselines (beet_baselines_hourly) are not subject to the same retention window. They represent aggregated statistics, not raw events, and are retained indefinitely. This ensures that a beet that has been running for years maintains its full historical baseline even on the Free plan.

Partition-aware deletion

The beet_events table is partitioned by received_at (monthly partitions). The DELETE query against a partitioned table allows Postgres to eliminate entire partitions that fall outside the retention window, making cleanup very efficient even at high data volumes.

Impact of plan downgrades

If an organisation downgrades (e.g. from Starter to Free), events older than 30 days will be deleted on the next cron run. This cannot be reversed. Baselines are preserved.