dotnet-cqrs/docs/event-streaming/retention-policies/time-based-retention.md

2.4 KiB

Time-Based Retention

Delete events older than specified age.

Configuration

var policy = new RetentionPolicyConfig
{
    StreamName = "orders",
    MaxAge = TimeSpan.FromDays(90),  // Keep events for 90 days
    Enabled = true
};

await _policyStore.SetPolicyAsync(policy);

Common Retention Periods

Stream Type Retention Reason
Audit Logs 7 years Compliance (SOX, GDPR)
Order Events 90-365 days Business analytics
Analytics 30-90 days Short-term insights
Debug Logs 7-30 days Troubleshooting
Notifications 7-14 days Recent history only

Usage Examples

Compliance (7 Years)

await _policyStore.SetPolicyAsync(new RetentionPolicyConfig
{
    StreamName = "audit-logs",
    MaxAge = TimeSpan.FromDays(365 * 7),  // 7 years
    Enabled = true
});

Business Data (1 Year)

await _policyStore.SetPolicyAsync(new RetentionPolicyConfig
{
    StreamName = "orders",
    MaxAge = TimeSpan.FromDays(365),  // 1 year
    Enabled = true
});

Short-Term Logs (30 Days)

await _policyStore.SetPolicyAsync(new RetentionPolicyConfig
{
    StreamName = "application-logs",
    MaxAge = TimeSpan.FromDays(30),  // 30 days
    Enabled = true
});

SQL Implementation

CREATE OR REPLACE FUNCTION apply_time_retention(
    p_stream_name TEXT,
    p_max_age_seconds INTEGER
) RETURNS INTEGER AS $$
DECLARE
    deleted_count INTEGER;
BEGIN
    DELETE FROM events
    WHERE stream_name = p_stream_name
      AND timestamp < NOW() - (p_max_age_seconds || ' seconds')::INTERVAL;

    GET DIAGNOSTICS deleted_count = ROW_COUNT;
    RETURN deleted_count;
END;
$$ LANGUAGE plpgsql;

Monitoring

public async Task<RetentionStats> GetRetentionStatsAsync(string streamName)
{
    var policy = await _policyStore.GetPolicyAsync(streamName);
    var oldestEvent = await GetOldestEventAsync(streamName);
    var eventsToDelete = await CountEventsOlderThanAsync(
        streamName,
        DateTimeOffset.UtcNow - policy.MaxAge);

    return new RetentionStats
    {
        OldestEventAge = DateTimeOffset.UtcNow - oldestEvent.Timestamp,
        EventsToDelete = eventsToDelete,
        RetentionPeriod = policy.MaxAge
    };
}

See Also