conf 0.70what we believed then, about then
Each node and edge version has two times: valid time, when the fact was true in the world, and recorded time, when the system recorded it. The two can differ, for example when a change is recorded after it took effect.
The same query can be asked at different combinations of the two times. The four combinations below show what the system recorded on March 5 and what it records now, about March 11 and about today.
Fictional example. Drag the two sliders. The top one sets recorded time, when the system recorded the fact. The bottom one sets valid time, when the fact was true in the world. The query under the chart updates to match.
The same query. belief-99 was revised on 2026-06-01 — from HIGH_RISK to LOW_RISK after KYC completed. Ask what the system had recorded before the revision → HIGH_RISK 0.70. Ask what it recorded after → LOW_RISK 0.95.
In this example the risk service updates belief-99 in place: AT VALID '2026-06-01' MATCH (b:Belief {id: 'belief-99'}) SET b.claim = 'LOW_RISK', b.confidence = 0.95. If you use db.reviseBelief instead, each revision is a new node; use db.beliefLineage('belief-99') to walk the revisions.
InvariantDB stores two times on every node and edge version: when the fact was true (valid time) and when it was recorded (recorded time).
The customer's KYC status became verified on 2026-06-01. That's a fact about the world — it happened whether or not any system captured it in the same instant.
Valid time answers “what was true then?” You can set the start of a fact’s valid time to a past or future date with the AT VALID write prefix. A later AT VALID write ends the earlier value’s valid time at the new date. Every change is kept in the history log.
The KYC document didn't arrive at the risk service until 2026-06-03 at 14:22 UTC — two days later. That's a fact about our record-keeping, not the world.
Recorded time answers “what had the system recorded?” The server sets it when the write is applied, and it cannot be backdated. A correction adds a new version; the earlier version stays in the hash-chained history log.
Fix one time and vary the other to see how answers change.
conf 0.70conf 0.70conf 0.70conf 0.95AT VALID and AT RECORDED
Attach AT VALID, AT RECORDED, or both to a MATCH pattern. The pattern is matched against the graph as it was at that time.
MATCH pattern — they immediately follow the pattern and rewind the store before the pattern is executed. They do not attach to WITH, WHERE, or RETURN. Put filters and projections after the temporal clauses.
Put AT VALID before the first clause to set when the written facts became true. The recorded time is always the time of the write. Without the prefix, a write is valid from the moment it is recorded.
A later AT VALID write ends the earlier value’s valid time at the new date. A write dated before a value recorded for a later date is refused when it would replace that later version and lose one of its values (WRITE_WOULD_REPLACE_LATER_VERSIONS, from release 1.4.2.5); write the change at or after the later date. A query without a time answers what is valid now, so a value dated in the future is returned from its date on (from release 1.4.2.4). Closed intervals such as AT VALID FROM … TO … are refused with CLOSED_INTERVAL_WRITE_UNSUPPORTED. A DELETE ends the fact at the time of the delete, or at the AT VALID time when the statement has one; a delete that would end a fact before it starts is refused. On a query that only reads, the prefix is applied as the valid time of each MATCH that has no temporal clause of its own.
AS OF t is the same as AT RECORDED t. OVER VALID BETWEEN a AND b and OVER RECORDED BETWEEN a AND b return one row per version that overlaps the window. The atTime field on POST /graphs/{name}/cypher and on the MCP cypher_query tool applies AT VALID to each top-level MATCH; it is refused when a MATCH already has a temporal clause or when the query has no top-level MATCH.
n._valid_from, n._valid_to, n._txn_from, n._txn_to, and n._version return milliseconds since the Unix epoch. _valid_to and _txn_to are null while the version is open. Integer arguments to AT VALID and AT RECORDED are read as nanoseconds, so pass ISO-8601 strings in queries.
Fictional example. On March 5 the risk service returned HIGH_RISK for a customer and the application declined them. After KYC completed on June 1, the same customer is LOW_RISK. Both values are stored; the later one does not erase the earlier one.
Ask the store to rewind to March 5. The KYC document hadn't arrived yet. belief-99 was on revision 1, backed by two source episodes. The service returned HIGH_RISK with 0.70 confidence — and the decline queue kicked in.
Without a temporal clause, the query returns the current value, written after KYC verified the customer on June 1. Confidence is 0.95. The earlier value is still in the history log and can be read with AT RECORDED.
Move the recorded-time and valid-time controls and see the query result change. No signup required.