Skip to content

sergueif/pseudotime_demos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

Pseudotime Demos

A collection of demos showing how an app can adopt the pseudotime pattern in its data layer.

What is pseudotime?

Pseudotime is a lightweight approach to temporal data that lets you query "what did the data look like at point N in time?" without any wallclock machinery or event-sourcing infrastructure.

Instead of real timestamps, each row carries a monotonically incrementing integer — the pseudotime — that advances once per write transaction. Writes never mutate existing rows in place; instead they expire the old revision and insert a new one. This makes full history retention and point-in-time reads a natural consequence of the schema rather than a bolt-on.

Why not just use timestamps?

Wall-clock timestamps carry hidden problems: clock drift, skew across machines, timezone ambiguity, and the inability to express "strictly before this event" rather than "before this millisecond." A pseudotime counter sidesteps all of that. It advances exactly once per transaction, giving you a clean causal ordering with no clock machinery involved. Two events that coincide in wall-clock time are still strictly ordered; two events that happen milliseconds apart are indistinguishable if no write separates them — which is exactly the right semantics for data history.

This makes pseudotime a genuinely different thing from SQL:2011 temporal tables or most SCD Type 2 implementations, which tie history to real timestamps and inherit their problems. The closest real-world analogues are Datomic's transaction t value (each write increments a logical counter; db.asOf(t) queries at that point) and Git (a repository is a "world," each commit is a pseudotime tick, git checkout <sha> is a point-in-time read).

What is a world?

A world is the unit of causal isolation: the scope within which the pseudotime counter is authoritative and consistent. All writes to the same world share a single counter; writes to different worlds are causally independent and carry no ordering relationship to each other.

Where you draw the world boundary is a domain decision, not a framework decision. A multi-tenant app might give each tenant its own world. A simulation might fork worlds to explore "what if" scenarios. A workflow engine might isolate each job. No database feature or ORM can infer this boundary for you, because it reflects the semantics of your application.

Core columns every pseudotime table carries:

Column Meaning
eid Stable entity ID (same across all revisions of one logical record)
created_at_pseudotime The pseudotime at which this revision was born
valid_before_pseudotime The pseudotime at which this revision was superseded (nil = still current)

A point-in-time query for pseudotime T filters for rows where created_at_pseudotime <= T and (valid_before_pseudotime >= T or valid_before_pseudotime is nil).

Properties:

  • Immutable writes — updates expire the old revision (set valid_before_pseudotime) and insert a new one
  • Deletes without a successor — deletions only expire the current row; no new revision is inserted
  • Full history — the entire audit trail lives in the same table, no separate log needed
  • World isolation — multiple independent timelines ("worlds") coexist in the same tables

Demos

Demo Stack Description
ruby-sqlite Ruby + SQLite via Sequel A simple todo list showing inserts, updates, and deletes — then time-travel queries back through the history

Further reading

  • David P. Reed — Naming and Synchronization in a Decentralized Computer System (MIT PhD thesis, 1978) The foundational treatment of treating mutable objects as sequences of immutable versions named by an integer counter, with synchronization as the mechanism for ordering those versions. The pseudotime schema is a direct descendant of this model.

  • Rich Hickey — Are We There Yet? (JVM Language Summit keynote, 2009) Argues that time should be understood as a derivative of observing a succession of immutable values — not as a property of mutable objects. Introduces the epochal time model that underlies Datomic and motivates designs like pseudotime.

About

Demos and prototypes of using pseudotime (for concurrency and history access)

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors