Fauna Temporal Reads: Query Past Document States Without an Audit Table
Use Fauna's At() and VersionAt() to read historical document states directly, but confirm retention limits and service availability before relying on them for compliance.
12 Oct 2026, 05:05 UTC

The problem: you only know what a record looks like now
A support ticket arrives: a customer's billing address changed last week, and the team needs to know the previous value. Your application stores only the current document. Without a separate audit table, answering "what did this record say at time T?" means reconstructing history from logs or accepting that the data is gone.
How Fauna's temporal reads work
Fauna's storage engine keeps multiple versions of every document using MVCC (multi-version concurrency control). FQL exposes that history through two read-only functions:
At(timestamp, expression)evaluates a read expression as if the database were at that point in time.VersionAt(timestamp, reference)returns a specific version of a single document reference.
These functions wrap reads only. They do not version writes, and they are not exposed through Fauna's auto-generated GraphQL API.
Worked example: read a user as it existed last week
Run this in Fauna Shell or through an official driver. You need a server or admin key with read permission on the documents and indexes referenced inside At().
At(
Time("2026-10-05T12:00:00Z"),
Get(Match(Index("users_by_email"), "[contact removed]"))
)
Replace the timestamp and index name with your own. The expected result is the document's field values at that instant, not the current version. If the timestamp falls outside your configured history retention, the query may return an error or no historical version rather than the older state. Temporal reads can also cost more read throughput than live reads because they scan historical versions.
You can wrap Paginate or aggregations inside At() to time-travel an entire result set, not just one document.
Trade-offs and limits
| Factor | Practical implication |
|---|---|
| History retention | Finite and configurable. Hosted plans were commonly cited around 30 days, but this varies by plan and engine version. Check your own console or CLI before assuming a window. |
| Read cost | Historical scans can cost more than live reads. Benchmark before using At() on a hot path. |
| Writes | At() and VersionAt() do not version writes. Deleting a document does not create an undo point outside the retention window. |
| Service status | Fauna's hosted cloud service was reported to have shut down in 2025. Confirm whether your endpoint is self-hosted, a fork, or unavailable before building on it. |
Verify before you rely on it
- Check your Fauna console or CLI for the configured history retention in days and confirm it covers your audit window.
- In a test database, create a document, update it, then run
At(previous_timestamp, Get(ref))andVersionAt(previous_timestamp, ref). Diff the output against the current document. - Compare the read cost of a temporal query against the live equivalent using your driver or shell diagnostics.
- If your Fauna endpoint is unreachable, prototype your migration target's audit or temporal features on a small dataset first.
Bottom line
Fauna's temporal reads remove the need for a dual-write audit table for questions like "what did this record say at time T?" But the history window is finite, reads can cost more, and the hosted service status is uncertain as of late 2026. Verify retention, test the syntax against your exact FQL version, and treat indefinite time travel as something that requires exports or a dedicated store.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.