logo
  • Docs
  • API Reference
    Introduction
    What is Lix?
    Getting Started
    Comparison to Git
    Lix for AI Agents
    Essentials
    How Lix Works
    Querying Changes
    Data Model
    Plugins
    Persistence
    Guides
    Versions (Branching)
    History
    Diffs
    Attribution (Blame)
    Change Proposals
    Validation Rules
    Undo/Redo
    Restore
    Conversations
    Labels
    Key-Value Store
    Environment API
    Testing
    React Integration
    Logging & Debugging
    Deterministic Mode
    Metadata
    Writer Key
    Architecture
    Lix as File Format
    Previous pageLogging & DebuggingNext pageMetadata

    #Deterministic Mode

    Who is this for? If you're testing, debugging, or simulating distributed systems with Lix and need predictable, reproducible behavior across runs, deterministic mode is for you.

    Use deterministic mode for:

    • Testing - Unit and integration tests that produce identical results every run
    • Debugging - Reproduce exact sequences of events from bug reports
    • Simulations - Run deterministic simulations across multiple environments

    #Quick Example

    Normal mode (default) - different results each run:

    import { openLix, getTimestamp, random } from "@lix-js/sdk";
    
    const lix = await openLix({ blob });
    
    getTimestamp({ lix }); // "2024-03-15T10:32:45.123Z" (current time)
    getTimestamp({ lix }); // "2024-03-15T10:32:45.124Z" (real time passes)
    random({ lix }); // 0.7234... (unpredictable)
    random({ lix }); // 0.1823... (unpredictable)

    Deterministic mode - same results every run:

    const lix = await openLix({
      blob,
      keyValues: [
        {
          key: "lix_deterministic_mode",
          value: {
            enabled: true,
          },
          lixcol_version_id: "global",
        },
      ],
    });
    
    getTimestamp({ lix }); // "1970-01-01T00:00:00.000Z" (always epoch)
    getTimestamp({ lix }); // "1970-01-01T00:00:00.001Z" (always +1ms)
    random({ lix }); // 0.318... (always this sequence)
    random({ lix }); // 0.937... (always this sequence)

    #Configuration

    #Basic Setup

    Enable deterministic mode when opening a Lix:

    const lix = await openLix({
      blob,
      keyValues: [
        {
          key: "lix_deterministic_mode",
          value: {
            enabled: true,
          },
          lixcol_version_id: "global",
        },
      ],
    });

    Or enable it after opening:

    await lix.db
      .updateTable("key_value_all")
      .set({ value: { enabled: true } })
      .where("key", "=", "lix_deterministic_mode")
      .where("lixcol_version_id", "=", "global")
      .execute();

    #Configuration Options

    The deterministic mode is configured through a single key-value object:

    KeyTypeDescription
    lix_deterministic_modeobjectConfiguration object for deterministic mode

    The configuration object has the following properties:

    PropertyTypeDefaultDescription
    enabledbooleanrequiredEnable/disable deterministic mode
    randomLixIdbooleanfalseUse random lix_id for distributed testing
    timestampbooleantrueUse deterministic timestamps
    random_seedstring"lix-deterministic-seed"Seed for the random number generator
    nano_idbooleantrueUse deterministic nano ID generation
    uuid_v7booleantrueUse deterministic UUID v7 generation

    #Advanced Usage

    #Distributed Testing with Random Lix IDs

    For distributed testing scenarios where you need multiple Lix instances with different IDs:

    // Creates Lix instances with random IDs for distributed testing
    const lix1 = await openLix({
      keyValues: [
        {
          key: "lix_deterministic_mode",
          value: {
            enabled: true,
            randomLixId: true, // Each instance gets a random lix_id
          },
          lixcol_version_id: "global",
        },
      ],
    });
    
    const lix2 = await openLix({
      keyValues: [
        {
          key: "lix_deterministic_mode",
          value: {
            enabled: true,
            randomLixId: true, // Different from lix1
          },
          lixcol_version_id: "global",
        },
      ],
    });
    NOTE
    • Use default deterministic mode (enabled: true) for reproducibility testing (e.g., unit tests, regression tests)
    • Use randomLixId mode (enabled: true, randomLixId: true) for distributed testing scenarios (e.g., simulating multiple Lix instances syncing)

    #Different RNG Seeds

    To make multiple Lix instances behave differently in deterministic mode:

    // Set seed when opening
    const lix1 = await openLix({
      blob,
      keyValues: [
        {
          key: "lix_deterministic_mode",
          value: {
            enabled: true,
            random_seed: "instance-1",
          },
          lixcol_version_id: "global",
        },
      ],
    });
    
    // Or update seed after opening using SQLite's json_set function
    import { sql } from "@lix-js/sdk";
    
    await lix.db
      .updateTable("key_value_all")
      .set({
        value: sql`json_set(value, '$.random_seed', 'instance-2')`,
      })
      .where("key", "=", "lix_deterministic_mode")
      .where("lixcol_version_id", "=", "global")
      .execute();

    #State Persistence

    Deterministic state is automatically persisted:

    EventState Flushed?
    Successful mutating transaction✅
    lix.toBlob() / lix.close()✅
    Read-only transaction❌
    Transaction rollback/error❌

    #API Reference Quick-Links

    The following functions provide deterministic behavior when lix_deterministic_mode is enabled:

    FunctionPurposeDocs
    getTimestamp({ lix })Logical clock timestampsAPI docs
    random({ lix })Reproducible random numbersAPI docs
    uuidV7({ lix })Deterministic UUID v7 generationAPI docs
    nanoId({ lix })Deterministic nano ID generationAPI docs
    nextSequenceNumber({ lix })Monotonic counter (advanced)API docs