API reference / @evolu/common / local-first / Timestamp

Variable: Timestamp

const Timestamp: ObjectType<{
  counter: BrandType<
    BrandType<
      Type<
        "Brand",
        number & Brand<"Int"> & Brand<"NonNegative">,
        number,
        NonNegativeError,
        number & Brand<"Int">,
        IntError | NumberError
      >,
      "LessThanOrEqualTo65535",
      LessThanOrEqualToError<65535>,
      NonNegativeError | IntError | NumberError
    >,
    "Counter",
    BrandWithoutRefineError<
      "Counter",
      NonNegativeError | IntError | NumberError | LessThanOrEqualToError<65535>
    >,
    never
  >;
  millis: BrandType<
    BrandType<
      Type<
        "Brand",
        number & Brand<"Int"> & Brand<"NonNegative">,
        number,
        NonNegativeError,
        number & Brand<"Int">,
        IntError | NumberError
      >,
      `LessThanOrEqualTo${number}`,
      LessThanOrEqualToError<number>,
      NonNegativeError | IntError | NumberError
    >,
    "Millis",
    BrandWithoutRefineError<
      "Millis",
      NonNegativeError | IntError | NumberError | LessThanOrEqualToError<number>
    >,
    never
  >;
  nodeId: BrandType<
    Type<"String", string, string, StringError, string, StringError>,
    "NodeId",
    RegexError<"NodeId">,
    StringError
  >;
}>;

Defined in: packages/common/src/local-first/Timestamp.ts:169

Hybrid Logical Clock timestamp.

Timestamps serve as globally unique, causally ordered identifiers for CRDT messages in Evolu's sync protocol.

Why Hybrid Logical Clocks

Evolu uses Hybrid Logical Clocks (HLC), which combine physical time (millis) with a logical counter. This hybrid approach preserves causality like logical clocks while staying close to physical time for better human interpretability.

The counter component ensures causality is maintained even when physical clocks are imperfect. When clocks drift or operations occur concurrently, the counter increments to establish a total order. This means Evolu achieves well-defined, eventually-consistent behavior regardless of physical clock accuracy.

Vector clocks can accurately track causality and detect concurrent operations, but they require unbounded space in peer-to-peer systems and crucially, still don't solve our fundamental problem: when they detect operations as concurrent, we still need a deterministic way to choose a winner. Additionally, any deterministic conflict resolution can be gamed by malicious actors.

HLC timestamps work well in practice because modern device clocks accurately reflect the order of sequential edits in the common case. Evolu's maxDrift configuration protects against buggy clocks and prevents problematic future-dated entries from propagating through the network.

References

Privacy Considerations

Timestamps are metadata visible to relays and collaborators. While it can be considered a privacy leak, let us explain why it's necessary, and how to avoid it if maximum privacy is required.

With real-time communication, participants always see activity (receiving bytes). We cannot trust anyone not to store that information, so explicitly exposing timestamps doesn't add additional risk.

If we really want not to leak user activity, we can implement a local write queue:

  1. Write changes immediately to a local-only table
  2. Periodically and randomly flush messages to sync tables

Trade-off: It breaks real-time collaboration.

Was this page helpful?