go-auditGo Audit
Features

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.

createt0
updatet1
snapshott2
updatet3
snapshot point — reconstruct entity state up to here

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.

snapshot.go
// 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.

restore.go
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)
}
Restore is not destructive — the previous state remains in audit logs. But it does overwrite live rows, so production restores should always be approved out-of-band.

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.

ForeverNo purge — full history
180 daysDefault ops retention
7 yearsFinancial / SOX compliance
cron.go
// 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)
Purge is irreversible. Deleted entries cannot be reconstructed. Snapshot any time-travel cutoff before running purge in production.

On this page