From 1b7b2eb0a42b166dc7d77a1a48355060b8a09c00 Mon Sep 17 00:00:00 2001 From: Vadko Date: Mon, 9 Mar 2026 02:48:55 +0200 Subject: [PATCH] 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). --- templates/compose/supabase.yaml | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/templates/compose/supabase.yaml b/templates/compose/supabase.yaml index 75d5a1e25..86268158b 100644 --- a/templates/compose/supabase.yaml +++ b/templates/compose/supabase.yaml @@ -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