← Blog · Engineering · August 25, 2026 · 7 min read · By Operate Technical Staff

Connection Reset by Peer Is a Decision, Not a Failure: Proving Which Component Sent the RST

A production attribution guide to connection reset by peer: the six components that can send a TCP RST, their timing signatures, and how to prove which one did it.

Connection Reset by Peer Is a Decision, Not a Failure: Proving Which Component Sent the RST

Connection Reset by Peer Is a Decision, Not a Failure: Proving Which Component Sent the RST

TL;DR: A connection reset by peer error (ECONNRESET) indicates your kernel received a TCP RST packet for an established connection, immediately discarding the socket. This is an intentional act by a specific component—such as a load balancer, firewall, or service mesh sidecar—rather than a random network failure, and can be attributed by analyzing timing signatures and platform-level metrics.

What the error actually records

In production logs, this error appears as connection reset by peer, surfaced as ECONNRESET (errno 104) on Linux, errno 54 on macOS, or WSAECONNRESET (10054) on Windows. It is critical to correct the record on two common misconceptions:

  1. It is not an HTTP status code. While search engines often surface queries for "HTTP code 104," 104 is a POSIX errno. There is no such thing as an HTTP 104 status.
  2. It is not the same as "Connection Refused." A connection refused (ECONNREFUSED) occurs when a RST is received in response to your initial SYN packet because no listener exists on that port. ECONNRESET happens only after a connection is established.

When this error occurs, your kernel receives a TCP segment with the RST (Reset) bit set. It immediately tears down the connection, flushes the buffers, and notifies your application.

Why the reset destroys its own evidence

In a graceful shutdown, both ends exchange FIN packets, allowing in-flight data to be processed and log lines to be written. A RST is an abortive signal; it is a single segment that provides no acknowledgement of intent.

The primary difficulty in debugging connection reset by peer is that the component sending the RST often does so because it has already lost the state for the connection or is acting at a layer below the application. Consequently, the "other side" frequently has no log entry for the event. If a load balancer resets an idle connection, your backend application may never even know a connection existed. This is why "checking the other service's logs" is often a dead end.

Reset, broken pipe, refused, timeout: A four-way distinction

Error Kernel Signal Timing Meaning
Connection Reset RST Mid-stream or after idle The peer (or a middlebox) aborted the connection.
Broken Pipe EPIPE During a write You tried to write to a socket the peer already reset.
Connection Refused RST During SYN (handshake) No process is listening on the target port.
Timeout N/A No response The packet was dropped or the peer is too slow to respond.

The six components entitled to send a RST

1. The Peer Application

The remote application may explicitly call abort() or set SO_LINGER with a timeout of zero. Most commonly, this happens if the application closes a socket while there is still unread data in its receive buffer.

2. The Peer Host's Kernel

If a host receives a packet for a TCP 4-tuple (source IP/port, dest IP/port) it doesn't recognize, it sends a RST. This happens during process crashes, container restarts, or when a client reuses a pooled connection that the server host has already forgotten.

3. Proxy or Load Balancer Idle Timeout

Managed services like AWS ALB, HAProxy, or Nginx have idle timeouts. If no data flows for $X$ seconds, they unilaterally send a RST to both the client and the server to reclaim resources.

4. Stateful Firewalls and Conntrack

Network Address Translation (NAT) and firewalls maintain a "conntrack" table. If the table is full, or if a connection stays idle longer than the conntrack timeout, the firewall evicts the entry. Subsequent packets for that connection are treated as invalid and met with a RST.

5. The TLS Layer

During the TLS handshake, a mismatch in SNI, ALPN, or an expired certificate can trigger a RST before any application data is sent. According to autocomplete data, this is increasingly common with LLM providers (OpenAI, Ollama) and is often misreported as a transport error.

6. Service Mesh Sidecars (Envoy/Istio)

In a mesh, the sidecar manages the connection lifecycle. If a pod is being terminated, the sidecar (Envoy) might shut down before the application container finishes its last few requests, leading to resets at the edge of a deployment.

Attribution when you can capture packets

If you can run tcpdump, do not just look for the RST. Compare the IP TTL (Time to Live) and IP ID fields of the RST against successful packets from the peer. If the TTL of the RST is different from the TTL of the data packets, the RST was injected by a middlebox (firewall or proxy) rather than the peer host.

Attribution when you cannot capture packets

In 2026, most production environments use managed services (AWS ALB, API Gateway, Cloudflare) where packet capture is impossible. In these cases, use the Evidence Exclusion method:

The Decision Table

Observed Pattern Environment Probable Originator Confirming Test
Exactly 60s/300s idle AWS ALB / Nginx Proxy Idle Timeout Lower client pool idle time < LB timeout
During Pod Rollout Kubernetes / Istio Mesh Sidecar Race Check PreStop lifecycle hooks
During SSL Handshake OpenAI / vLLM TLS / SNI Mismatch Test with curl -v or check cert expiry
Random under high load Linux Node Conntrack Eviction Monitor nf_conntrack_count
Immediate on write Managed DB / Redis Kernel State Loss Check for peer process restarts

Why this matters

The request path has grown significantly. A single call now traverses client pools, cloud load balancers, Ingress controllers, mesh sidecars, and kube-proxy NAT before reaching a managed backend. According to Devrim Ozcay, blaming the network is usually a waste of time because the network is merely the messenger for a configuration mismatch between these components.

Common pitfalls

Sources & further reading

Key Takeaway: A TCP reset is not a failure of the network, but a deliberate decision by a specific component that can be identified by its timing signature and platform-layer metrics.

Identifying these patterns manually is the core of modern SRE work. At Operate, our AI SRE platform automates this by correlating connection pool metrics against conntrack saturation and proxy logs to find the evidence for a reset. By bucketing reset rates by their likely originator, Operate helps teams move past "network blip" excuses and provides the specific configuration PRs needed to align timeouts across the stack.

#networking#sre#kubernetes#tcp#troubleshooting