Basic Prerequisites: 02 · The FIX Protocol (message structure, 35/34/43/122).
1. Intuition & Practical Objective
The session layer is what makes FIX more than a message format: it is a recovery protocol. Two engines open a TCP connection, exchange Logon (35=A), and from that moment keep a pair of monotone counters - one for each direction - so that a gap, a crash, or a reconnect is detectable and repairable. The practical objective of this page: know exactly how sequence numbers advance, how a gap becomes a ResendRequest, how the resend is answered, and how heartbeats prove a peer is alive.
The one idea to hold onto: a sequence number is a receipt for a message the sender kept. Because the sender journals every message it emits, it can always replay any range on demand. The receiver’s counter says “here is what I still need”; the sender’s log says “here is everything I ever sent”. Together they reconstruct a stream that TCP alone could not guarantee after a restart.
2. Mathematical Ground Truth & Derivations
The two counters. Each side maintains:
On sending, . The receiver’s rule on receiving MsgSeqNum = M is the core of the whole protocol:
The gap size is : exactly messages are missing, and the request covers .
Answering a resend. The sender replays stored messages in with PossDupFlag(43)=Y and OrigSendingTime(122) set to the message’s original send time - so the receiver can tell a resend from a new message. Replayed administrative messages (Logon A, Heartbeat 0, ResendRequest 2) are not re-sent as-is; they are collapsed into a SequenceReset-GapFill (35=4, 123=Y, 36=NewSeqNo) that advances the receiver’s counter past them. Application messages are re-sent.
SequenceReset in two modes - a critical distinction:
A bare reset is the mechanism by which missed orders are forgotten - intentionally, during a session “resynchronisation”, and dangerously if used to paper over a bug.
Heartbeats and the liveness contract. With HeartBtInt = H seconds:
The TestRequest demands a Heartbeat bearing the same TestReqID(112); no reply means the peer is dead and the session must be torn down rather than left half-open.
Resend log sizing. The outbound log must hold at least the largest plausible outage: for rate (msg/s) and outage seconds, the backlog is messages, bytes/s of storage. This is the operational cost of the reliability guarantee.
3. Computational Implementation - a session with gap detection and resend
We model both sides of a FIX session: an outbound log for replay, an expected-inbound counter, gap detection, resend request, and the gap-fill that resynchronises the counters. Stdlib only.
Read the trace as the recovery proof: the server sees seq=3 while expecting 1, reports a gap of size , requests exactly [1,2], accepts the two replayed PossDup messages, and then accepts seq=3 - ending with , identical to the sender’s . The two counters converge; that is session correctness.
4. Failure Modes & First-Principles Breakdowns
- Losing the log on crash (sequence blow-up). If
N_outis persisted but the messages are not, the engine must answer aResendRequestit cannot satisfy. The only legal recovery is aSequenceResetthat admits the loss - which means the venue may never learn of orders your engine sent. Journaling is not optional; it is the receipt. - Duplicate execution from a naïve replay. A resent
ExecutionReportcarries43=Y; if you process it as new you double the fill. This is the classic desync (worked in 05 · Failure Modes). - The
SequenceReset-Resetfoot-gun.123=N(hard reset) discards the messages in the reset range. Using it to clear a stubborn gap hides real orders; only gap-fill (123=Y) is safe for routine resends. - Midday logon with a stale sequence. Reconnecting with the wrong
MsgSeqNuminLogontriggers either a resend or aSequenceNumberTooLowreject; the recovery is deterministic but only if the engine knows which of its counters the venue last saw. - Half-open sockets. TCP keep-alive is far too slow (minutes) for a trading session; without FIX heartbeats you can sit quoting into a dead link. The
TestRequest/Heartbeatexchange is the only timely liveness proof. - Heartbeat interval too long.
HeartBtIntis a latency ceiling on failure detection: a 30 s interval means up to 30 s of trading into a dead peer. Venues often mandate a range (commonly 10–60 s). - Clock skew on
OrigSendingTime. Resends carry52(new send time) and122(original send time); a receiver that validates52strictly, or a sender with skewed clocks, creates spurious rejects.
5. References
- FIX Trading Community, *FIX 4.4 Specification, Volume 2
- FIX Trading Community, *FIX Latest
- OnixS, FIX Dictionary & Protocol Reference
6. Connected Graph Bridges
- Back: 02 · The FIX Protocol
- Forward: 04 · Order Lifecycle & Connectivity · Index Hub
- Deep-dive: 05 · Failure Modes (desync and duplicate execution)
- Context: Low-Latency Systems Architecture (why the log and the session sit in the hot path)