NV
NordVarg
ServicesTechnologiesIndustriesCase StudiesBlogAboutContact
Get Started

Footer

NV
NordVarg

Software Development & Consulting

GitHubLinkedInTwitter

Services

  • Product Development
  • Quantitative Finance
  • Financial Systems
  • ML & AI

Technologies

  • C++
  • Python
  • Rust
  • OCaml
  • TypeScript
  • React

Company

  • About
  • Case Studies
  • Blog
  • Contact

© 2025 NordVarg. All rights reserved.

November 12, 2025
•
NordVarg Team
•

FIX Protocol Fundamentals: How FIX Works and Why It Still Matters

Tradingfixtradingprotocolsinfrastructure
6 min read
Share:

The Financial Information eXchange (FIX) protocol remains the lingua franca of electronic trading. Despite the rise of native binary feeds and exchange-specific APIs, FIX still powers order entry, trade reporting, allocations, and many post-trade workflows. This article explains the practical parts of FIX you need to operate and debug production trading systems.

Why FIX still matters#

FIX is widely supported by brokers, ECNs, and most institutional counterparties. Its advantages are:

  • Ubiquity: almost every market participant understands FIX message flows.
  • Extensibility: custom tags and application messages let firms transport proprietary data.
  • Clear session semantics: sequence numbers, heartbeats, and resend logic provide a well-defined recovery model.

At the same time, FIX is text-based and verbose, which means parsing and resiliency patterns are important for production systems.

High-level architecture: layers of FIX#

FIX is typically conceptualized in two layers:

  • Session layer (FIXT / FIX session): manages connection state, sequencing, recovery, heartbeats, and logon/logout.
  • Application layer: application messages such as NewOrderSingle (order entry), ExecutionReport (fills), Allocation messages, and trade capture.

Transport is commonly over TCP and often wrapped in TLS for encryption. Many firms place a FIX gateway or OEMS in front of their trading application to handle session-level concerns and provide journaling/replay.

Message anatomy — what a FIX message looks like#

A FIX message is a sequence of tag=value fields delimited by ASCII SOH (0x01). For readability we often show fields separated by | (pipe) — remember the real delimiter is SOH.

Example: a minimal NewOrderSingle (FIX 4.4 style)

8=FIX.4.4|9=0123|35=D|49=CLIENT12|56=BROKER1|34=2|52=20251112-12:34:56.789|11=ORDER123|55=ABC|54=1|38=100|40=2|44=10.50|59=0|10=128

Key fields in the example:

  • 8 BeginString (protocol version)
  • 9 BodyLength (number of bytes in body)
  • 35 MsgType (D = NewOrderSingle)
  • 49 SenderCompID (client)
  • 56 TargetCompID (broker)
  • 34 MsgSeqNum (sequence number)
  • 52 SendingTime (timestamp)
  • 11 ClOrdID (client order id)
  • 55 Symbol
  • 54 Side (1 = buy, 2 = sell)
  • 38 OrderQty
  • 40 OrdType (2 = Limit)
  • 44 Price
  • 59 TimeInForce
  • 10 CheckSum (three-digit checksum)

The real production message must calculate 9 (BodyLength) and 10 (CheckSum) correctly — many gateways and libraries do this automatically.

Session management: keeping the conversation reliable#

Fix sessions have explicit semantics to handle disconnection and out-of-order messages.

  • Logon / Logout: A session starts with a Logon message (35=A) and ends with Logout (35=5).
  • Heartbeats & Test Requests: Heartbeats (35=0) are exchanged periodically. If a peer doesn't respond, a Test Request (35=1) can be sent to verify liveliness.
  • Sequence numbers: Each message carries a MsgSeqNum (tag 34). If a receiver sees a gap, it should request resend (35=2 - ResendRequest) and the sender should respond with Sequence Reset or the missing messages.
  • Resend semantics: resend may include a GapFill (message type /G) which tells the receiver to advance its sequence without replaying message content.

A typical session-management loop:

  1. Send Logon (35=A). If the counterparty accepts, session is established.
  2. Exchange heartbeats. If heartbeat missed, send Test Request.
  3. If MsgSeqNum gaps appear, issue ResendRequest and process replay.
  4. On disconnect, persist your outgoing sequence number and messages so you can resume.

Example: simple send/receive loop (pseudocode)#

python
1# Pseudocode: minimal reliable sender loop (conceptual)
2out_seq = load_out_seq_from_persistent_store()
3pending_journal = load_unacked_messages(out_seq)
4
5# attempt to (re)establish session
6send(LogonMessage)
7
8# resend any un-acked messages if necessary
9for msg in pending_journal:
10    send(msg)
11
12while session_active():
13    event = poll_socket()
14    if event.type == MESSAGE:
15        if event.msg.SeqNum > in_seq + 1:
16            # gap detected
17            send(ResendRequest(start=in_seq+1, end=0))
18        elif event.msg.SeqNum == in_seq + 1:
19            process_application_message(event.msg)
20            in_seq += 1
21    elif event.type == SEND_ORDER:
22        msg = build_new_order(...)
23        msg.SeqNum = out_seq + 1
24        journal.append(msg)           # persist to disk before send
25        send(msg)
26        out_seq += 1
27        persist_out_seq(out_seq)
28

Key practical rule: persist outgoing messages and sequence numbers before acknowledging to your internal systems. That way, if you crash and restart, you can replay the journal and avoid duplicate/missing messages.

Handling common failure modes#

  • Sequence gaps: Usually caused by dropped messages or a crash. Use ResendRequest and the session replay to heal. Ensure both sides implement gap-fill semantics correctly.
  • Out-of-order messages: Reorder using MsgSeqNum or request a resend.
  • Sticky sessions and load balancing: Many exchanges require sticky TCP sessions. If you load-balance FIX connections, ensure the balancer preserves TCP affinity or use a FIX gateway to multiplex connections.
  • Duplicate messages: Be idempotent on ClOrdID where possible and deduplicate by OrderID/ExecID on the server side.

Example messages: ExecutionReport (fill)#

An ExecutionReport notifying a partial fill might look like:

8=FIX.4.4|9=0120|35=8|49=BROKER1|56=CLIENT12|34=10|52=20251112-12:35:03.123|37=EX123|11=ORDER123|17=FILL1|150=1|39=1|55=ABC|54=1|38=100|14=50|6=10.50|151=50|10=064

Important fields:

  • 37 OrderID (broker-assigned)
  • 17 ExecID (execution id)
  • 150 ExecType (trade type)
  • 39 OrdStatus
  • 14 CumQty
  • 151 LeavesQty

Processing an ExecutionReport must update order state and reconcile ClOrdID with local order objects.

Tools and diagnostics#

  • Wireshark: has a FIX dissector (configure to show SOH or use the pipe representation). Use it to inspect raw messages and sequence numbers.
  • quickFIX / quickfixj / quickfixn: robust open-source FIX engines. Use their logs and message journals for replay.
  • Broker logs / gateway journals: many brokers provide replay endpoints and diagnostic tools.
  • Monitoring: track retransmit counts (ResendRequest frequency), message latency, and message rates.

Testing FIX integrations#

  • Use a test harness or simulated peer (many brokers offer sandbox FIX endpoints).
  • Include UI and headless tests that exercise session recovery: simulate disconnects and sequence gaps and verify replay behavior.
  • Implement trybuild-like integration tests where a fake counterparty drives corner cases (e.g., out-of-order replay, gap-fills introducing sequence-reset).

Security and operational concerns#

  • TLS: prefer TLS for public-facing links. Use mutual TLS where possible.
  • IP whitelisting: exchanges and broker partners often restrict connections to known IPs.
  • Rate limits and flow control: some venues will throttle or drop connections at high message rates; respect quotas.
  • Credential rotation: treat SenderCompID/TargetCompID and certificates as sensitive.

Best practices checklist (quick)#

  • Persist outbound messages and sequence numbers before sending.
  • Implement ResendRequest and GapFill handling fully.
  • Ensure idempotency and deduplication on processing ExecutionReports.
  • Test session recovery regularly (automated chaos tests help).
  • Monitor retransmits, message rates, and session health metrics.
  • Keep a clear audit trail (journaling) for post-trade reconciliation.

Conclusion#

FIX is foundational to electronic trading. The protocol's explicit session semantics (sequencing, resend, heartbeats) make it well-suited for robust order entry and post-trade workflows — provided you implement persistence, replay, and observability. For production systems, focus on correctness first (durable journaling, replay), then optimize for latency and throughput.


Appendix: Quick checklist for debugging a broken FIX session#

  • Confirm network connectivity (TCP/TLS) and correct target/sender IDs.
  • Check sequence numbers in both directions; identify any gaps.
  • Search logs for ResendRequest / Sequence Reset messages.
  • Use Wireshark to capture raw traffic and confirm the delimiter and checksums.
  • Replay persisted outgoing messages after reconnect if necessary.
NT

NordVarg Team

Technical Writer

NordVarg Team is a software engineer at NordVarg specializing in high-performance financial systems and type-safe programming.

fixtradingprotocolsinfrastructure

Join 1,000+ Engineers

Get weekly insights on building high-performance financial systems, latest industry trends, and expert tips delivered straight to your inbox.

✓Weekly articles
✓Industry insights
✓No spam, ever

Related Posts

Nov 12, 2025•7 min read
FIX in Production: Hardening Sessions, Recovery and Resilience
Tradingfixinfrastructure
Nov 12, 2025•7 min read
Smart Order Routers (SOR): Design and Strategy
Tradingsorrouting
Nov 14, 2025•6 min read
Market Microstructure & Latency Engineering: Measuring and Reducing Tail Latency
Tradinglatencymicrostructure

Interested in working together?