# Ordering & Replay (/learn/concepts/ordering-and-replay)



Imagine a deli counter that hands out numbered tickets. Everyone is served in the order they arrived — ticket 41 before 42 before 43 — and the numbers never repeat or skip. Now imagine the deli also kept a logbook of every ticket it ever served. A clerk arriving for the late shift could open the book, find where the morning clerk left off, and pick up from exactly that ticket — no customer served twice, none missed.

Those two ideas — **serving in a fixed order** and **rewinding the log to any point** — are *ordering* and *replay*. They are what separate a fleeting stream of notifications from a durable, rebuildable record of what happened.

## Ordering — the idea [#ordering--the-idea]

**Ordering** is the guarantee about *what sequence consumers observe messages in*. The strongest common form is **FIFO** (first-in, first-out): messages come out in exactly the order they went in. A queue gives you this naturally — like a single-file line, the message enqueued first is delivered first.

<Mermaid
  chart="graph LR
  P[&#x22;Producer&#x22;]
  Q[[&#x22;Orders queue<br/>FIFO&#x22;]]
  W[&#x22;Worker&#x22;]

  P -- &#x22;enqueue #1&#x22; --> Q
  P -- &#x22;enqueue #2&#x22; --> Q
  P -- &#x22;enqueue #3&#x22; --> Q
  Q -- &#x22;deliver #1, then #2, then #3&#x22; --> W

  class Q queue
  class P,W client"
/>

*A FIFO queue delivers messages in the exact order they were enqueued.*

Global FIFO across an entire channel is simple but limits throughput — only one consumer can safely process at a time without reordering. In practice most systems offer **per-key ordering** instead: messages that share a *partition key* (an order ID, a user ID) stay strictly ordered relative to each other, while unrelated keys flow in parallel. You get order where it matters and parallelism everywhere else.

## Replay — the idea [#replay--the-idea]

A real-time channel is a PA announcement: hear it now or miss it forever. A **replayable** channel is a recording. To replay, the system has to do two things:

1. **Number every message** with a monotonically increasing **sequence number** (also called an **offset**) — a stable address for each message in the log.
2. **Persist the log*&#x2A; so messages survive after delivery, and let a consumer say &#x2A;"start me at offset N"* instead of always "start me at the newest."

<Mermaid
  chart="graph LR
  PUB[&#x22;Publisher&#x22;]
  ES{{&#x22;Events Store<br/>orders.events&#x22;}}
  DISK[(&#x22;Persistent log<br/>seq 1 … 100&#x22;)]
  LIVE[&#x22;Live subscriber<br/>(from newest)&#x22;]
  REPLAY[&#x22;Late subscriber<br/>(replay from seq 42)&#x22;]

  PUB -- publish --> ES
  ES --- DISK
  ES -- &#x22;stream new&#x22; --> LIVE
  ES -. &#x22;replay history&#x22; .-> REPLAY

  class ES store
  class DISK data
  class PUB,LIVE,REPLAY client"
/>

*Every message is numbered and written to a persistent log; a late subscriber rewinds to any offset and re-reads history, while a live subscriber follows the tail.*

Because the log keeps the sequence intact, replay and ordering reinforce each other: re-reading from offset 42 always returns 42, 43, 44… in the same order, every time. That determinism is what makes a log trustworthy as a system of record.

### The event-sourcing idea [#the-event-sourcing-idea]

If the log is the source of truth, you do not need to store the *current state* of anything — you can **rebuild it by replaying the events that produced it**. This is **event sourcing**: instead of saving "account balance = $80," you save the sequence of facts (`Deposited $100`, `Withdrew $20`) and replay them to compute the balance on demand. A new service, a rebuilt cache, or a bug fix that needs to reprocess history all start the same way: replay from the beginning.

<Callout type="info">
  **Concept:** A sequence number (offset) is just a message's permanent position in the log. "Replay" means asking the log to start delivering from a chosen position instead of from the newest message.
</Callout>

## Precise definition [#precise-definition]

* **Ordering** — a delivery guarantee that consumers observe messages in a defined sequence. **FIFO** orders an entire channel; **per-key ordering** orders only messages sharing a partition key, allowing parallel processing across keys.
* **Sequence number / offset** — a monotonically increasing integer assigned to each message as it is persisted, giving every message a stable, addressable position in the log.
* **Replay** — re-reading messages from a persisted log starting at a chosen **start position** (a sequence number, a timestamp, the first message, or the last), rather than receiving only messages published after subscribing.
* **Event sourcing** — modeling state as the ordered log of events that produced it, and reconstructing current state by replaying that log from the start.

## Trade-offs [#trade-offs]

| Property                     | When it helps                                                           | When it bites                                                                        |
| ---------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| **Strict FIFO**              | Steps that must happen in order (state machines, financial postings)    | Caps throughput — one in-flight consumer per ordered stream                          |
| **Per-key ordering**         | Order per entity (per order, per user) plus parallelism across entities | Requires choosing a good key; a hot key still serializes                             |
| **Persistent log + offsets** | Late joiners, audit trails, reprocessing, event sourcing                | Costs disk and retention management; the log grows                                   |
| **Replay from a position**   | Recovery, backfills, rebuilding state from history                      | Re-delivering old events can re-trigger side effects if consumers are not idempotent |

<Callout type="warn">
  **Pitfall:** Replaying history re-delivers messages a consumer may have already handled. If processing a message has side effects — charging a card, sending an email — make consumers **idempotent** (safe to run twice for the same message), keyed on the sequence number or a message ID. Otherwise a replay double-charges. See [delivery guarantees](/learn/concepts/delivery-guarantees) for idempotency.
</Callout>

## In KubeMQ [#in-kubemq]

<Callout type="info">
  **In KubeMQ:** **Queues** preserve FIFO order — messages are delivered in the order they were sent. **Events Store** persists every message with a **sequence number** and lets a subscriber choose a **start position**: `StartNewOnly`, `StartFromFirst`, `StartFromLast`, `StartAtSequence`, `StartAtTime`, or `StartAtTimeDelta`. Pointing a subscriber at `StartFromFirst` and rebuilding state from the result is exactly event sourcing.
</Callout>

The snippet below subscribes to a persisted channel from **sequence 3** — replaying every stored event at or after that offset, then streaming new ones as they arrive. Swapping `StartAtSequence` for `StartFromFirst` replays the entire history; `StartAtTimeDelta` replays a recent time window.

<Tabs groupId="language" items="['Go','Python','Node.js','Java','C#','Kotlin','C++','Rust','Ruby','Elixir']">
  <Tab value="Go">
    ```go title="replay_from_sequence.go"
    sub, err := client.SubscribeToEventsStore(ctx, "orders.events", "",
        kubemq.StartAtSequence(3),
        kubemq.WithOnEvent(func(event *kubemq.Event) {
            fmt.Printf("[replay] seq=%d body=%s\n",
                event.Sequence, string(event.Body))
        }),
        kubemq.WithOnError(func(err error) { log.Println(err) }),
    )
    ```
  </Tab>

  <Tab value="Python">
    ```python title="replay_from_sequence.py"
    client.subscribe_to_events_store(
        subscription=EventsStoreSubscription(
            channel="orders.events",
            start_position=EventStoreStartPosition.StartAtSequence,
            start_position_value=3,
            on_receive_event_callback=lambda e: print(
                f"[replay] seq={e.sequence} body={e.body.decode('utf-8')}"
            ),
            on_error_callback=lambda e: print(f"Error: {e}"),
        ),
        cancel=CancellationToken(),
    )
    ```
  </Tab>

  <Tab value="Node.js">
    ```typescript title="replay_from_sequence.ts"
    client.subscribeToEventsStore({
      channel: 'orders.events',
      startPosition: EventStoreStartPosition.StartAtSequence,
      startPositionValue: 3,
      onEvent: (msg) =>
        console.log(`[replay] seq=${msg.sequence} body=${new TextDecoder().decode(msg.body)}`),
      onError: (err) => console.error(err.message),
    });
    ```
  </Tab>

  <Tab value="Java">
    ```java title="ReplayFromSequence.java"
    client.subscribeToEventsStore(EventsStoreSubscription.builder()
        .channel("orders.events")
        .startPosition(EventStoreStartPosition.StartAtSequence)
        .startPositionValue(3)
        .onReceiveEventCallback(event ->
            System.out.printf("[replay] seq=%d body=%s%n",
                event.getSequence(), new String(event.getBody())))
        .onErrorCallback(err -> System.err.println(err.getMessage()))
        .build());
    ```
  </Tab>

  <Tab value="C#">
    ```csharp title="ReplayFromSequence.cs"
    await foreach (var msg in client.SubscribeToEventsStoreAsync(
        new EventsStoreSubscription
        {
            Channel = "orders.events",
            StartPosition = EventStoreStartPosition.StartAtSequence,
            StartPositionValue = 3,
        }))
    {
        Console.WriteLine($"[replay] seq={msg.Sequence} body={Encoding.UTF8.GetString(msg.Body.Span)}");
    }
    ```
  </Tab>

  <Tab value="Kotlin">
    ```kotlin title="ReplayFromSequence.kt"
    client.subscribeToEventsStore {
        channel = "orders.events"
        startPosition = StartPosition.StartAtSequence
        startPositionValue = 3
    }.collect { msg ->
        println("[replay] seq=${msg.sequence} body=${String(msg.body)}")
    }
    ```
  </Tab>

  <Tab value="C++">
    ```cpp title="replay_from_sequence.cc"
    client->SubscribeToEventsStore("orders.events", "",
        kubemq::StartPosition::StartAtSequence, 3,
        [](const kubemq::EventStoreReceived& msg) {
            std::cout << "[replay] seq=" << msg.sequence()
                      << " body=" << msg.body() << std::endl;
        },
        [](const std::string& err) { std::cerr << err << std::endl; });
    ```
  </Tab>

  <Tab value="Rust">
    ```rust title="replay_from_sequence.rs"
    use kubemq::prelude::*;
    use kubemq::EventsStoreSubscription;

    let sub = client
        .subscribe_to_events_store(
            "orders.events",
            "",
            EventsStoreSubscription::StartAtSequence(3),
            |event| {
                Box::pin(async move {
                    println!(
                        "[replay] seq={} body={}",
                        event.sequence,
                        String::from_utf8_lossy(&event.body)
                    );
                })
            },
            None,
        )
        .await?;
    ```
  </Tab>

  <Tab value="Ruby">
    ```ruby title="replay_from_sequence.rb"
    sub = KubeMQ::PubSub::EventsStoreSubscription.new(
      channel: "orders.events",
      start_position: KubeMQ::PubSub::EventStoreStartPosition::START_AT_SEQUENCE,
      start_position_value: 3
    )
    client.subscribe_to_events_store(sub, cancellation_token: cancel, on_error: lambda { |e|
      puts "Error: #{e.message}"
    }) do |event|
      puts "[replay] seq=#{event.sequence} body=#{event.body}"
    end
    ```
  </Tab>

  <Tab value="Elixir">
    ```elixir title="replay_from_sequence.exs"
    {:ok, sub} =
      KubeMQ.Client.subscribe_to_events_store(client, "orders.events",
        start_at: {:start_at_sequence, 3},
        on_event: fn event ->
          IO.puts("[replay] seq #{event.sequence}: #{event.body}")
        end
      )
    ```
  </Tab>
</Tabs>

<Callout type="info">
  Queues deliver in FIFO order with no start-position parameter — order is inherent to the queue. The start positions above apply to **Events Store**, where the persistent log makes any offset addressable.
</Callout>

### How KubeMQ does this → [#how-kubemq-does-this-]

<Cards>
  <Card title="Events Store" href="/learn/events-store" description="Persistent pub/sub: every message gets a sequence number and survives for replay." />

  <Card title="Replay from Any Position" href="/learn/events-store/tutorials/replay-events" description="All six start positions — replay history from a sequence, a time, or the beginning." />

  <Card title="Event Sourcing" href="/learn/events-store/tutorials/event-sourcing" description="Rebuild application state by replaying the event log from the start." />

  <Card title="Queues" href="/learn/queues" description="Durable FIFO work queues that deliver messages in the order they were sent." />
</Cards>
