Skip to content

Full Ordering Flow

End to end — how message ordering works in the final design

Putting all the pieces together: client sends, server assigns seq, DynamoDB stores, client displays in seq order.


The complete flow

Alice sends "hey":
  1. Alice's client sends message over WebSocket
     payload: { content: "hey", client_timestamp: "4:20:00", message_id: "msg_aaa" }

  2. WS-Server-1 receives the message
     → calls INCR seq:conv_abc123 on Redis
     → gets seq=42

  3. WS-Server-1 writes to DynamoDB:
     PK=conv_abc123, SK=42
     content="hey", sender=alice, receiver=bob
     message_id=msg_aaa, timestamp=4:20:00, s3_ref=null

  4. WS-Server-1 delivers to Bob:
     → looks up Bob's ws_server_id in Redis registry
     → forwards to Bob's WS server
     → Bob's WS server pushes to Bob's WebSocket:
       { seq: 42, content: "hey", sender: alice, timestamp: "4:20:00" }

  5. Bob's client:
     → stores message at seq=42
     → renders in conversation sorted by seq

What the client holds and how it renders

Bob's client maintains a local sorted list of messages by seq:

seq=40  Alice: "how was your day"   4:19:55
seq=41  Bob:   "pretty good"        4:19:58
seq=42  Alice: "hey"                4:20:00

When a new message arrives, the client inserts it at the correct seq position. If messages arrive out of order over the network (seq=44 before seq=43), the client holds seq=44 in a buffer and waits briefly for seq=43 before rendering.


Network reordering with seq numbers

The original problem was network reordering — packets arriving out of order. With seq numbers, the client handles this cleanly:

Arrives first:  seq=44 "hello??"    → buffer it, waiting for seq=43
Arrives second: seq=43 "you there"  → now have 43 and 44, render both in order
Arrives third:  seq=42 "hey"        → have 42, 43, 44, render all three in order

The seq number is the anchor. Regardless of network arrival order, the client always renders in seq order.


Summary — what each component does

Client timestamp  → display only ("4:20 PM" shown under the message)
                    client fills this, server stores it as-is

seq_no            → ordering only (what position this message occupies in conversation)
                    server assigns via Redis INCR, stored as DynamoDB sort key

DynamoDB SK       → seq_no (sorted within partition, enables range reads for history)

Client rendering  → sort by seq_no, display client_timestamp

These three concerns — display time, ordering, storage — are fully decoupled. Each is solved by the right tool for the job.