ZagTrader

FIX Message Rate: Messages per Second, Peak Rate and Message Mix from a FIX Log

The FIX message rate is the number of messages a session or engine handles per unit of time. The analyzer counts every message in the log, places it in time by its log timestamp or SendingTime (52), and reports the average rate, the busiest second, the busiest minute and the mix by MsgType (35) and direction. The peak, not the average, is what sizes queues, threads and network links.

Free and in your browser: the log is read and analysed on your computer, nothing is uploaded.

What the analyzer shows

Messages
Every FIX message found in the log, counted once, whatever its type or session.
Time span
From the first to the last message on the timeline clock: the timestamp written in front of each log line, or SendingTime (52) for lines without one.
Average rate
Messages with a time, divided by the time span in seconds.
Peak rate (busiest second)
The highest number of messages whose time falls in the same whole second, and the second it happened.
Busiest minute
The same count per whole minute. It shows sustained load that a single busy second can hide.
Message rate over time
Messages per interval through the log, stacked by category. The interval is chosen so the log fits in about 150 bars: 1 s, 5 s, 10 s, 30 s, 1 min, 5 min, 10 min, 15 min, 30 min, 1 h and longer steps.
Category
Rejects: Reject (35=3), Business Message Reject (35=j), Order Cancel Reject (35=9) and Execution Reports with 150=8 or 39=8. Session: the other admin messages (35=0, 1, 2, 4, 5 and A). Order requests: 35=D, F, G, H, E, AB, AC, q, AF, s, t, u, K, L, M, x and c. Executions: other Execution Report (35=8) plus 35=r, N, AE and AR. Market data: 35=V, W, X and Y. Everything else is Other.
Message mix by MsgType
A count for every MsgType (35) value in the log, with inbound and outbound counts for each.
Inbound and outbound
Read from the direction marker on the log line (IN or OUT, sent or received, <== or ==>). Lines without a marker are counted as no direction.
Session and application messages
Session messages are the admin types 35=0, 1, 2, 3, 4, 5 and A; application messages are all the others.
Sessions and versions
A session is one BeginString (8) with one pair of SenderCompID (49) and TargetCompID (56), in either direction. Messages are also counted per BeginString.

Example from the demo log

These figures are calculated from the demo trading day that the analyzer loads with See it on the demo log, so they match what you see there. In the analyzer every bar and row opens the FIX messages behind it.

Messages

11,022

3 sessions

Average rate

0.45/s

over 6 h 45 min

Peak second

62/s

at 16:00:00

Busiest minute

81

from 09:33

Inbound

6,993

outbound 4,029

Session messages

2,540

application 8,482

Message rate over time

Messages per 5 min, stacked by category

09:2512:5016:10

SessionExecutionsOrder requestsRejects

Message mix by MsgType

Count per MsgType (35), inbound and outbound

MsgTypeNameCountInOut
35=8Execution Report5,8895,8890
35=0Heartbeat2,5221,0881,434
35=DNew Order Single2,04102,041
35=FOrder Cancel Request3600360
35=GOrder Cancel/Replace Request1850185
35=ALogon633
35=5Logout633
35=9Order Cancel Reject550
35=3Reject440
35=AFOrder Mass Status Request101

By category

Share of all messages

  • Rejects 24
  • Order requests 2,587
  • Executions 5,875
  • Session 2,536
  • FIX.4.44,357
  • FIX.4.23,420
  • FIXT.1.13,245

Messages per BeginString (8)

Demo log: one generated trading day (2026-10-19) on three FIX sessions (FIX 4.2, FIX 4.4 and FIXT.1.1).

In the demo day the log holds 11,022 messages on 3 sessions over 6 h 45 min, an average of 0.45 messages per second. The busiest second, at 16:00:00, carries 62 messages and the busiest minute, from 09:33, carries 81: the peak second is about 137 times the average rate, which is why capacity is planned on the peak.

Execution Report (35=8) is the most frequent type with 5,889 messages (53.4% of the log), followed by Heartbeat (35=0) with 2,522. Session messages make up 23.0% of the log and application messages 77.0%.

6,993 messages are inbound and 4,029 outbound. Every New Order Single in this log is outbound and every Execution Report inbound: the log was written on the order-sending side, where one order brings back several reports.

How to read it: what good and bad look like

  • Size for the peak. Engines, queues and links fail at the busiest second, not at the average. A peak many times the average is normal for trading, which bunches at the open, the close and around news.
  • Compare the busiest second with the busiest minute. A high second inside an ordinary minute is a burst; a busy minute means sustained load, which is what builds queues.
  • Look at the stacked chart for the shape of the day. Order requests and executions should follow the market; a block of session messages with no order flow is usually a reconnect, a resend or a quiet session that only heartbeats.
  • A Heartbeat share that is large on a quiet session is expected: with nothing else to send, each side sends one every HeartBtInt (108) seconds. On a busy session Heartbeats should almost disappear, because any message resets the interval.
  • Rejects in the mix deserve a look even when they are few; the reject analysis page ranks them by reason.
  • Inbound and outbound counts that differ widely are normal for order flow (one order can produce several Execution Reports), but not for session messages, which should be close to balanced on each session.
  • The rate is only as precise as the times in the log. If the log has no timestamps and messages carry SendingTime to the second, the busiest second is approximate.

Common causes and fixes

When a figure on this page looks wrong, these pages explain the errors most often behind it and how to fix them.

For engines: POST a log to the API

The same statistics are available over HTTP for scripts, monitoring jobs and engines. POST a log as text, gzip or a multipart file and get JSON, an HTML report or a plain-text summary back. The request is processed in memory and not stored.

curl --data-binary @fix.log -H "Content-Type: text/plain" "https://fixparser.zagtrader.com/api/v1/analyze"

Fields in the JSON response for this page:

  • stats.overview.messages: messages in the log
  • stats.overview.avgPerSecond: average rate
  • stats.overview.peakPerSecond: busiest second: count and ms
  • stats.overview.busiestMinute: busiest minute: count and ms
  • stats.overview.inbound, .outbound: direction split
  • stats.msgTypes[]: code, name, count, inbound, outbound per MsgType
  • stats.categories: messages per category
  • stats.timeline.buckets[]: messages per interval, by category
Read the API documentation

Questions

How do I measure FIX messages per second from a log?
Load the log in the analyzer and open the Analytics view. It reads the timestamp of every line (or SendingTime (52) when the line has none), counts messages per second and per minute, and shows the average rate, the busiest second and the busiest minute with the time each happened.
Which time does the message rate use?
The timestamp the log writer put in front of each line. Lines without one are placed by their SendingTime (52). The time source used is stated in the summary, so you know whether the rate reflects when your engine saw the messages or when the sender stamped them.
Why is the peak rate so much higher than the average?
Trading is uneven. Most of the day can be quiet with Heartbeats, while the open, the close and market events produce bursts. The average spreads those bursts over the whole log, which is why capacity should be planned on the peak second and the busiest minute.
Are resent messages counted?
Yes. Messages resent with 43=Y after a Resend Request (35=2) appear again in the log and are counted again, so a large resend can show up as a spike of messages. The session health page shows the resend requests and gap fills behind it.
What counts as a session message?
The admin message types: Heartbeat (35=0), Test Request (35=1), Resend Request (35=2), Reject (35=3), Sequence Reset (35=4), Logout (35=5) and Logon (35=A). Everything else is an application message.

Reference

More of what the analyzer measures

  • Order outcomes: How every order ended: filled, partly filled, cancelled, expired, rejected or open, with fill, reject and cancel rates.
  • Execution analysis: Execution Reports by ExecType (150), partial and full fills, and the fill-size distribution from LastQty (32).
  • Trading activity: Volume and traded value per symbol and currency, side, order type, time in force, venues, order-to-trade and cancel-to-fill.
  • Order latency: New order to ack, first fill, cancel and replace times, and Test Request to Heartbeat: p50, p90, p99 and max.
  • Reject analysis: SessionRejectReason, OrdRejReason, CxlRejReason and BusinessRejectReason ranked, Text (58) grouped, CheckSum and BodyLength errors.
  • Session health: Per session: heartbeats, test requests, sequence gaps, resends and gap fills, resets, logons, logouts and the longest silence.
  • FIX Log Analyzer: every statistic, how privacy works and how to start