feat: add configurable analytics log retention via pg_cron

- Add ANALYTICS_RETENTION_DAYS env var (default: 7) to supabase-db
- Create _analytics.cleanup_old_logs() function that deletes old
  log_events_* records based on app.analytics_retention_days setting
- Add analytics-retention.sh init script that:
  - Sets app.analytics_retention_days from ANALYTICS_RETENTION_DAYS env var
  - Schedules nightly cleanup at 03:00 UTC via pg_cron

Postgres backend has no built-in log retention, causing unbounded
growth of _analytics.log_events_* tables (~700MB/week typical).
This commit is contained in:
Vadko 2026-03-09 02:48:55 +02:00
parent a43e3b56e1
commit 1b7b2eb0a4

View file

@ -397,6 +397,7 @@ services:
- POSTGRES_DB=${POSTGRES_DB:-postgres}
- JWT_SECRET=${SERVICE_PASSWORD_JWT}
- JWT_EXP=${JWT_EXPIRY:-3600}
- ANALYTICS_RETENTION_DAYS=${ANALYTICS_RETENTION_DAYS:-7}
volumes:
- supabase-db-data:/var/lib/postgresql/data
- type: bind
@ -666,7 +667,50 @@ services:
\c _supabase
create schema if not exists _analytics;
alter schema _analytics owner to :pguser;
-- Analytics log retention cleanup function
-- Deletes log_events older than app.analytics_retention_days (default: 7 days)
CREATE OR REPLACE FUNCTION _analytics.cleanup_old_logs()
RETURNS void AS $$
DECLARE
tbl text;
days int;
BEGIN
days := COALESCE(nullif(current_setting('app.analytics_retention_days', true), '')::int, 7);
FOR tbl IN
SELECT tablename FROM pg_tables
WHERE schemaname = '_analytics' AND tablename LIKE 'log_events_%'
LOOP
EXECUTE format(
'DELETE FROM _analytics.%I WHERE timestamp < NOW() - INTERVAL ''%s days''',
tbl, days
);
END LOOP;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
\c postgres
- type: bind
source: ./volumes/db/analytics-retention.sh
target: /docker-entrypoint-initdb.d/init-scripts/99-analytics-retention.sh
content: |
#!/bin/bash
set -e
DAYS=${ANALYTICS_RETENTION_DAYS:-7}
# Set retention days as a Postgres custom setting
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "_supabase" \
-c "ALTER DATABASE _supabase SET app.analytics_retention_days TO '$DAYS';"
# Schedule nightly cleanup at 03:00 UTC using pg_cron
psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "postgres" -c "
SELECT cron.schedule_in_database(
'cleanup-analytics-logs',
'0 3 * * *',
'SELECT _analytics.cleanup_old_logs()',
'_supabase'
) ON CONFLICT DO NOTHING;
" || true
# Use named volume to persist pgsodium decryption key between restarts
- supabase-db-config:/etc/postgresql-custom