Why Wi-Fi always looks fine after the outage — and what a flight recorder changes
Every diagnostic you run after a wireless failure runs on a network that has already recovered. That single fact explains most of the frustration in wireless support — and it is a recording problem, not an analysis problem.
Contents
The recovery problem
A user says the call dropped. By the time you reach the machine, the client is associated at −54 dBm, DNS resolves in 12 ms, and a speed test saturates the link. You have a healthy network and an unhappy user, and nothing in front of you connects the two. So the ticket gets the only honest label available: not reproducible.
Wireless networks are unusual in how completely they erase their own failures. A crashed process leaves a core dump. A failed HTTP request leaves a log line with a status code. A five-second roam failure at the edge of a cell leaves an association that succeeded on the fourth attempt and a client that looks, from every interface you can query, exactly like a client that never had a problem at all.
The information was there. It existed for a few seconds, in kernel counters, in driver scan tables, in supplicant state machines, in DHCP transaction IDs. Then the counters were overwritten, the scan table was refreshed, the state machine advanced, and the lease renewed. Post-hoc tooling arrives at a scene that has been cleaned.
What disappears, and how fast
The erasure is not uniform. Different layers forget at very different speeds, which is why partial evidence is so often misleading — the surviving layer becomes the explanation simply because it is the only one left.
| Signal | Typical lifetime | Why it goes |
|---|---|---|
| Instantaneous RSSI / noise | 1–2 seconds | Sampled value, never stored |
| Scan candidate list | seconds to ~1 minute | Overwritten by the next scan |
| Deauth / disassoc reason code | until next event | Not logged by most OS stacks |
| Retry and PHY-rate counters | cumulative, no timeline | Monotonic totals hide bursts |
| DHCP transaction detail | until lease renewal | No client-side history kept |
| Per-hop latency and loss | not recorded at all | Nothing samples it continuously |
| Roam decision inputs | never exposed | Lives inside driver firmware |
Notice the pattern: the fastest-decaying evidence is the evidence that distinguishes causes, while the slowest-decaying evidence — cumulative counters, current association state — is the kind that tells you almost nothing about a specific minute. That is the worst possible arrangement for anyone diagnosing after the fact.
Five causes that all look identical afterwards
Consider a client that lost usable service for roughly forty seconds and then recovered. Here are five genuinely different root causes. After recovery, all five present the same way: an associated client with good signal and a user who says it broke.
Roam failure at the cell edge
The client held on to a distant AP well past usefulness, then failed association to the better one several times before succeeding. Only the roam attempt timeline separates this from plain coverage loss.
DHCP lease change
The lease expired and the renewal returned a different address. The link never dropped; the sockets did. Radio evidence looks perfect throughout.
Band-steering flap
The controller pushed the client between 5 GHz and 6 GHz repeatedly. Each individual transition is legal and fast; the aggregate is unusable.
Upstream path loss
Association was flawless and the gateway responded, but everything beyond it black-holed. Any client-only check that stops at the gateway reports success.
Power state transition
The interface entered aggressive power save, or the host briefly slept. Frames were buffered, retried, and eventually dropped — with no error surfaced anywhere.
The remedies are not interchangeable. Lowering a roam threshold does nothing for a lease collision; extending lease time does nothing for band steering. Guessing costs a change window and rarely closes the ticket, because the next occurrence looks the same as the last one.
What a recorder has to keep
Aviation solved a version of this problem by deciding in advance which parameters matter and writing them continuously to a bounded medium. The insight is not the storage — it is the commitment to record before you know which flight will matter.
For a wireless client, the minimum set that separates the five causes above is smaller than people expect. It is not full packet capture. It is five layers, sampled on one clock:
Radio
RSSI, noise, channel, band, BSSID, PHY rate and retry deltas — sampled at ~1 Hz, plus every scan result set.
Association
Auth, assoc and 4-way handshake events with timing, and deauth/disassoc reason codes verbatim.
Addressing
Full DHCP transaction detail, lease boundaries, IPv6 RA changes and DNS resolution latency.
Path
Gateway and off-net reachability with RTT and loss, so 'the link is up' and 'the path works' stay separate claims.
Host
Interface transitions, sleep and wake, VPN state, power source — the boring rows that resolve half of all mysteries.
One clock
A monotonic timestamp per row. Without it, cross-layer correlation is guesswork dressed up as analysis.
The cost of always recording
The objection to continuous recording is always cost, and it is a fair one — a tool that burns battery or fills a disk gets uninstalled before the incident it was meant to catch. Which means the design target is not "as much data as possible" but "little enough that nobody turns it off".
Structured rows are what make that possible. A second of typical activity is on the order of a few hundred bytes once it is typed fields rather than frames, so days of history fit in a few hundred megabytes with a fixed ceiling. A ring buffer means the ceiling is absolute: the recorder never grows, and old rows are overwritten rather than accumulating.
$ radiochron record --retain 72h --size 512MiB[i] ring buffer 512 MiB · overwrite oldest · retention 72h[i] sampling radio 1Hz · events on change · path probe 5s[i] steady state: 0.4% CPU · 31 MiB RSS · 0 network egress
From rows to a verdict
Rows alone are not an answer. A timeline of forty thousand events is a different kind of unhelpful than an empty ticket. The step that matters is correlation: taking a window around the reported minute and asking which causal story is consistent with all five layers at once, rather than with the one layer you happened to look at.
A useful verdict has three properties. It names one cause. It carries a confidence value that can be low. And it lists the specific rows behind the claim, so the reader can disagree with the reasoning rather than with the tool.
The third property is the one that decides whether anyone trusts the output. A confident answer with no evidence is indistinguishable from a guess, and in an escalation it will be treated as one — correctly. "Roam failure, 0.91, here are the four rows" survives a vendor call. "Wi-Fi issue detected" does not.
Ruling out matters as much as ruling in. Half the value in an escalation is being able to say that DHCP, DNS and the upstream path were all healthy across the exact window, with the samples to show it. That is how a ticket moves from your queue to the right one.
What this looks like in practice
The workflow inverts. Instead of reproducing a failure, you go looking for one that was already captured. The user reports a time; you open that time; the evidence is there because it was recorded before anyone knew it would matter.
$ radiochron verdict --at "11:53"VERDICT roam_failure (confidence 0.91)11:52:58 RSSI -84 dBm sustained 6s · scan set empty11:53:04 assoc → Office_AP_6E timeout ×3 (status 16)11:53:12 gateway unreachable · 41s without default route11:53:53 reassociated Office_AP_6E · service restored[i] ruled out: dhcp_exhaustion, dns, upstream_loss, host_sleep$ radiochron bundle --at "11:53" --redact ssid,bssid,mac[i] wrote incident-2026-09-08-1153.rcz (2.1 MiB)
The change in the conversation is larger than the change in the tooling. "It happened again this morning" stops being the end of the investigation and becomes the start of one, because a timestamp is now enough to retrieve the evidence.
Limits worth stating
A client-side recorder sees what the client sees. It cannot read your controller's configuration, watch other clients contend for airtime, or observe interference that never reaches your radio. It infers the network's behaviour from one vantage point, and honest tooling should say so rather than implying omniscience.
It is also not a substitute for a sniffer when you genuinely need frames. The realistic division of labour is that the recorder runs all the time and tells you which minute and which channel deserve a capture — which is exactly the question a sniffer cannot answer for you, because it was not running either.
And a verdict remains a hypothesis. Confidence values exist because the evidence is sometimes ambiguous, and a tool that never reports uncertainty is not more accurate, only less useful. The goal is not to remove the engineer from the loop. It is to make sure that when the engineer arrives, the scene has not already been cleaned.
RadioChron is this idea, shipped
A local-first flight recorder for Wi-Fi: bounded continuous chronicle, a verdict engine that cites its evidence, and a desktop app to scrub the timeline. MIT / Apache-2.0.