Docs

Table history (time travel)

Keep every version of a table's rows and query the table exactly as it was at any moment — joins, filters and all.

Updated Oct 17, 2026Open in console

Turn history on for a table and Sovaria keeps every version of every row: what was inserted, each update and each delete, with the time it changed. sov_as_of(NULL::orders, '<time>') then returns the table exactly as it was at that moment, typed as the table itself, so it filters, joins and aggregates like any table. Use it to answer "what did this order look like yesterday?", audit a change, or copy back rows someone overwrote — without restoring a backup.

sov db history on orders --keep-days 7
sov db as-of orders "2 hours ago"
sov db as-of orders "2026-10-17 09:00+05:30" --where "id = 42"
sov db history list
sov db history off orders

How it works

  • Turning history on adds row triggers to the table and records the current rows as the starting point: history begins then, and earlier moments return no rows.
  • Each change closes the row's current version and adds the new one, stamped with the transaction's start time, so a transaction's changes appear together. Changing a primary key ends the old row and starts a new one; TRUNCATE ends every version.
  • The table needs a primary key (each row's versions follow its key). Columns added later read as NULL in older versions; dropped columns disappear from them.
  • Versions older than the retention are removed automatically, at most once a day per table, during a write to it.
  • Turning history off removes the triggers and deletes the stored versions. Dropping a table keeps its history with it in the trash, so undoing the drop brings both back.

Who can read history

History holds every past value of a table, beyond any row policy, so only the project team and the service key can read it. sov_as_of and sov_history are refused to app users, anon keys and custom API keys, and the history tables have row security that admits only team and service sessions. App users' own writes are still recorded.

Plans

FreeProUltraTeamEnterprise
Tables with history110502001,000
Days of history kept1 day7 days30 days90 days365 days

History is stored in your project database and counts toward its disk; the history tables and triggers don't count toward your table, trigger or index limits. Need the whole database at a past point instead? See point-in-time recovery in Database.

Something unclear or missing on this page?Tell us