Logon, heartbeats and logout
Heartbeat timeout: TestRequest unanswered, session disconnected
One side received nothing for longer than the heartbeat interval, sent a TestRequest (35=1), got no Heartbeat back carrying the same TestReqID, and dropped the connection.
What it means
At logon both sides agree HeartBtInt (108), in seconds. Each side sends a Heartbeat (35=0) whenever it has sent nothing else for that long, so silence longer than the interval means something is wrong.
When a side has heard nothing for slightly more than the interval, it sends a Test Request (35=1) with a TestReqID (112). The other side must answer at once with a Heartbeat carrying the same TestReqID. If that does not arrive either, the connection is treated as dead.
QuickFIX sends the TestRequest after about 1.2 heartbeat intervals of silence and disconnects after about 2.4, logging "Timed out waiting for heartbeat".
Common causes
- A firewall or NAT device dropping idle or long-lived TCP connections.
- The session thread blocked by slow application code, a long garbage-collection pause, or a full outbound queue, so heartbeats are not sent or read in time.
- A home-grown engine that sends heartbeats but does not answer TestRequest, or answers without echoing TestReqID (112).
- Different heartbeat intervals configured on each side.
- A network outage, in which case the timeout is working as intended.
How to fix it
On the side that went quiet
- Answer every TestRequest immediately with a Heartbeat that echoes TestReqID (112).
- Keep application work off the session thread so heartbeats are never delayed.
- Ask your network team about idle timeouts on firewalls between you and the counterparty.
On the side that timed out
- Check whether the counterparty went quiet or the network did: look for any inbound bytes before the timeout.
- Reconnect with normal sequence recovery. A heartbeat timeout does not need a sequence reset.
Example
A TestRequest and the Heartbeat that answers it. Without the second message the session would be dropped.
1. Sell side: TestRequest after a silence
8=FIX.4.4|9=77|35=1|49=SELLSIDE|56=BUYSIDE|34=3301|52=20261020-13:20:36.000|112=TEST-132036|10=053|
2. Buy side: Heartbeat echoing TestReqID
8=FIX.4.4|9=76|35=0|49=BUYSIDE|56=SELLSIDE|34=845|52=20261020-13:20:36.004|112=TEST-132036|10=017|
SOH (0x01) is shown as |. BodyLength (9) and CheckSum (10) are calculated as if every | were SOH.
Open this example in the parserQuestions
- What is a normal HeartBtInt?
- 30 seconds is the most common value. Low-latency venues often use shorter intervals; the value is whatever both sides agree.
- Do I need to send heartbeats while orders are flowing?
- No. Any message resets the timer. Heartbeats are only needed when you have nothing else to send.