Snapshots & Restore
Reconstruct any entity's exact state at any past moment. When you need to — or roll back live data. Every operation is itself recorded, so a restore is just another auditable event.
How snapshots work
Every Create, Update, and Delete captured by go-audit is stored as an immutable change record. Calling Snapshot(asOf) rewinds those records up to the moment you ask for, returning the entity exactly as it existed at that timestamp.
Capture a snapshot
Snapshot() takes an entity ID and a timestamp. Pass that asOf for the current state, or any past time. Use the past for a forensic audit. The replay is purely in-memory.
// reconstruct user 42 at the start of 2026
asOf := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
snap, err := auditor.Snapshot(ctx, "users", "42", asOf)
if err != nil {
return err
}
// snap.State is the user as it was on Jan 1.Restore an entity
Restore writes the historical data back into the live store, using a regular adapter write — every restore is itself a fresh audit entry. Idempotent — re-running a Restore at the same point you just restored to is a no-op.
target := time.Date(2026, 4, 27, 12, 0, 0, 0, time.UTC)
if err := auditor.Restore(ctx, "users", "42", target); err != nil {
log.Fatal(err)
}
Purge old logs
Snapshots only work for those ranges that still exist in the audit log. Run Purge as a scheduled job to drop entries older than your retention threshold — 7 years by default for SOX, 180 days for default ops.
// run nightly: drop entries older than 180 days
cutoff := time.Now().AddDate(0, 0, -180)
n, err := auditor.Purge(ctx, audit.PurgeOptions{
Before: cutoff,
Tables: []string{"audit_log", "audit_api_log"},
})
log.Printf("purged %d rows", n)