Skip to content

Overview

Simple Sync is a data storage system which uses the Event Sourcing pattern. It is meant to be optimized for usage as a backend for local-first apps.

Data is represented as a sequence of events.

Each event has the following schema of 6 fields, represented as a JSON object.

{
"uuid": "string",
"timestamp": "uint64",
"user": "string",
"item": "string",
"action": "string",
"payload": "string"
}
  1. All events are evaluated against the ACL.
  2. The UUID must be a valid v7 UUID.
  3. The timestamp must be a valid 64 bit unsigned integer representing the number of milliseconds since the epoch.
  4. The timestamp must match the timestamp value encoded in the UUID.
  5. The user, item, and action may contain any of the following characters:
    • Lowercase letters
    • Uppercase letters
    • Numbers
    • The following punctuation: ., /, :, -, and _
      • . is preferred as a separator between segments, for example: admin.123 rather than admin-123.
  6. Users, items, and actions that begin with . are reserved for internal usage and subject to additional validation.
  7. The payload must be a valid JSON object encoded as a string.

Any event that fails validation is not added to the authoritative history.

All data querying is handled locally. This means that Simple Sync is inappropriate for situations that require millions of items. It is much better suited for systems that need to store a small amount of items that don’t change too frequently.

The syncing process ensures that all clients have the latest version of the event history. Here’s a step-by-step breakdown:

  1. Authoritative History: The server maintains the authoritative history of all events. This is the single source of truth for the data.
  2. Initial Sync: When a new client comes online, it performs an initial sync by retrieving the entire authoritative history from the server via the API.
  3. Local Events: After the initial sync, the client keeps a local history of any events generated by the user on that client. These events are stored locally and represent changes that have not yet been synchronized with the server.
  4. Periodic Push: The client periodically pushes its local events to the server via the API. This is typically triggered by the user (e.g., with a “sync” button) to avoid conflicts during active use.
  5. Server-Side Merge: The server receives the incoming events from the client and merges them into the authoritative history, applying any necessary conflict resolution or validation logic. The server will also ensure that all events follow the rules defined in the ACL Specification.
  6. New Authoritative History: The server responds to the client’s push request with the updated authoritative history.
  7. Client Update: The client replaces its local copy of the authoritative history with the new version received from the server.

This process ensures that all clients eventually converge on the same state, while also allowing for offline work and local data access.