History and AS OF

A collection that keeps its history logs every change in the same transaction as the write: the record as it became, who changed it, when, and why.

Turn it on

Turn it on in the admin UI, or set "history": true in the schema. The rows the collection already has are logged once, as they stand, so the history starts complete.

Read the past

// the collection as it stood at the end of June
await sluurp.collection("grades").list({ asOf: "2026-06-30" });

// one record's versions, newest first; and bringing one back
await sluurp.collection("grades").history(id);
await sluurp.collection("grades").restore(id, seq, { reason: "Undo" });
GET /api/collections/grades/aggregate?op=avg&field=value&group=subject&asOf=2026-06-30

// every change, in order
GET /api/collections/grades/changes?since=0

Each past version is read through the collection’s view rule, as it applies to that version. History never shows a reader anything they could not have seen.

A moment of the past is rebuilt once and kept, so paging through it or asking again is fast. The server keeps a few moments per collection. If too many people ask for new moments at once, the extra requests get 429 Too Many Requests and can try again a second later, so looking at the past never slows everyone else down.

Say why

await sluurp.collection("grades").update(id, { value: 7 }, { reason: "Re-marked after appeal" });

Over HTTP, the X-Sluurp-Reason header does the same. A batch gives one reason for all of its changes.

In SQL

The SQL console in the admin UI understands SQL:2011’s temporal syntax. Plain SQL still reads the latest rows.

SELECT subject, avg(value)
FROM grades FOR SYSTEM_TIME AS OF '2026-06-30'
GROUP BY subject;

Before SQLite sees the query, each such table is replaced by its rows as they stood, rebuilt from the change log under the table’s own name. The same works in the browser on rows synced into SQLite.

Pages

Pages’ version history is the same log: who changed a page, when, and the reason they gave. Restoring a page means restoring one of its versions.