Logistics & Mobility// diagnostic

The map is open, the vehicles have stopped moving, and the data is fine

In short

Query the newest position row for one frozen vehicle and compare its server receipt time against the age the marker shows. If the row is fresh, the data plane is fine and the fault is transport or rendering — a socket that died without reconnecting, markers rebuilt instead of moved, or a background tab the browser throttled. Only a genuinely old row sends you to the ingest path.

Key takeaways

  • One query splits the system: newest row's server receipt time against the timestamp the marker displays.
  • A dropped socket with no reconnect is the most common cause, and it looks identical to a dead feed.
  • Reconnecting is not enough. Without a snapshot request on reconnect the map stays frozen until each vehicle pings.
  • Re-creating markers on every update instead of moving them is what makes 400 vehicles unusable in a browser.
  • A background tab has its timers clamped to roughly once a minute, so the map is stale before anyone looks at it.
  • Render the age of every position. A map that cannot say how old a marker is will eventually lie to a dispatcher.

Pick one vehicle that has stopped moving on the map and run a single query: the newest position row for that vehicle, ordered by server receipt time, not by device time. Compare that timestamp against the age the marker is showing. If the row is 20 seconds old and the marker says 14 minutes, the database has the data and something between it and the screen is not delivering it. That is the whole triage, and it takes a minute.

Do it in that order because the instinct is backwards. A frozen map looks like a data problem, so teams start with devices, SIMs and ingest queues — the slowest things to check and, in a fleet-wide freeze, the least likely. Transport and rendering fail more often, and they fail with no exception, no failed request and no alert. The screen simply stops changing.

The check that splits the system in half

  1. Query the newest row for one frozen vehicle, and read the server receipt timestamp. Device time is not usable here: a device with a wrong clock will make a fresh row look ancient or a stale one look current.
  2. Read the age the marker is displaying for the same vehicle. If your map does not display an age, stop and add one — you cannot run this comparison without it.
  3. Check whether the freeze is fleet-wide or a subset. Every vehicle frozen at once points at transport or rendering. A handful frozen while the rest move is a different investigation entirely, covered in most of the fleet updating and 11 vehicles stale since morning.
  4. Open the browser's network panel and look at the state of the live connection. An open socket with no messages for 3 minutes and a closed socket look identical on the map and have different repairs.
  5. Reload the page. If everything jumps to current and then freezes again minutes later, you have confirmed a transport problem without touching the backend.

The causes, ranked by how often they turn out to be it

CauseThe tellRepair
Socket closed, no reconnectReload fixes it; connection shows closed or silent in the network panelHeartbeat, backoff with jitter, and a snapshot request on reconnect
Reconnected but never resyncedPositions resume only as each vehicle happens to pingFetch current state on every reconnect before resuming the stream
Markers rebuilt instead of movedThe tab is pinned near full CPU and the whole page is sluggish, not just the mapMutate existing markers; move to a canvas layer above a few hundred
Unclustered rendering at scaleFine with 50 vehicles in view, unusable with 400Cluster, and subscribe only to vehicles inside the viewport
Background tab throttlingOnly stale when the dispatcher returns to the tab, then catches upResync on the visibility change event rather than trusting timers
Ingest lagThe newest row is genuinely old, and consumer lag is climbingThe ingest path, in that order: consumer lag, write batching, device cadence
Frozen-marker causes in the order worth checking, with the tell for each

The socket that died quietly

A live map is usually one long-lived connection carrying position updates. Long-lived is the operative word: something between the browser and your server has an opinion about how long a connection may sit idle, and a reverse proxy or corporate firewall closing an idle connection after about a minute is ordinary.

Worse, the close is often not clean. A laptop lid closes, a phone hands over between cell and wifi, a network device drops the flow silently — and the browser learns nothing until it tries to send. The symptom is a connection that reports itself open, delivering no messages, forever.

  • Send an application-level heartbeat every 20 to 30 seconds and expect one back. A transport-level keepalive you cannot observe is not a health check.
  • Treat 2 missed heartbeats as a dead connection and tear it down deliberately. Waiting for the network stack to notice can take many minutes.
  • Reconnect with exponential backoff and jitter, capped at about 30 seconds. Without jitter, a server restart brings every dispatcher's browser back simultaneously and the reconnect storm looks like a second outage.
  • On reconnect, request a full snapshot of current positions before resuming the stream. This is the step most often skipped, and skipping it means the map stays wrong until every vehicle has independently pinged — several minutes on a parked-vehicle cadence.
  • Show the connection state in the interface. A small "live" or "reconnecting" indicator turns an invisible failure into something a dispatcher reports in the first minute rather than the first hour.

A map that has silently stopped updating is worse than a map that is down. Nobody makes decisions from a blank screen; everybody makes decisions from a stale one.

Markers that get rebuilt instead of moved

The second-most common cause is a rendering pattern that is invisible at demo scale and fatal at fleet scale: on every update the map clears its markers and creates new ones. With 20 vehicles at a 30-second cadence nobody notices. With 400 vehicles reporting every 10 seconds, the browser is destroying and constructing 400 elements 40 times a minute, and the tab has no time left to paint.

The tell is that the whole page is sluggish rather than just the markers — scrolling stutters, buttons respond late, the fan spins. Three changes, in increasing order of effort.

  1. Mutate rather than recreate. Keep a map of vehicle id to marker and update the position of the existing marker. This is usually a small change and often removes the problem entirely.
  2. Coalesce updates to a fixed render rate. Buffer incoming positions and apply them 4 to 10 times a second rather than on arrival. Nobody can perceive a marker moving 40 times a second, and the browser is doing the work regardless.
  3. Move to a canvas or WebGL layer and cluster above a few hundred markers in view. Individually styled elements stop being viable somewhere in the low hundreds, and the exact number depends on your marker complexity, so measure it on the oldest machine in the dispatch office rather than on a developer laptop.

The tab nobody is looking at

Browsers aggressively throttle background tabs to save battery. Timers that should fire every second are clamped to roughly once a minute, animation callbacks stop entirely, and a tab that has been in the background for a while may be frozen outright. A dispatch map left open behind a spreadsheet is not updating on any schedule you chose.

The repair is to stop trusting timers and start listening for the visibility change event: when the tab becomes visible again, request a fresh snapshot and re-establish the connection if it is not healthy. Pair that with the age display on every marker, so a dispatcher returning to a tab sees "3 minutes ago" rather than a position presented as current. It is the same honesty problem that makes arrival detection firing late or twice at a stop so expensive: a system that presents an old observation as a current fact will be believed.

Only now, the ingest path

If the newest row really is old, the investigation moves behind the database, in this order: consumer lag on the ingest queue, then the write path, then the devices. Queue lag is the one that produces a fleet-wide freeze with everything else healthy — messages are arriving and waiting, and nothing reports an error because nothing has failed.

  • Consumer lag climbing steadily. Something downstream slowed — a slow write, an index rebuild, a scaled-down consumer group — and the backlog is the visible half of it.
  • Write batching set too generously. A 60-second flush interval is efficient and makes every position on the map up to a minute old before any of this starts.
  • A cadence policy doing exactly what it was told. Parked vehicles reporting every 15 minutes are not frozen, and the map should say so — which is the argument for setting ping cadence by what the vehicle is doing rather than one global interval.
  • A noise filter dropping legitimate updates. Filters that suppress stationary jitter, of the kind discussed in the parked truck that keeps moving, can be tuned tightly enough to swallow slow movement in a yard.

The reconnect-and-resync discipline is not specific to maps. Any long-lived integration needs it, and the decision about how work arrives in the first place sets a floor on how fresh anything downstream can be — the trade-off in booking by carrier API or tendering over EDI. A batch channel that lands every 15 minutes cannot feed a screen that claims to be live, however good the map code is.

The decision tree, in one pass

  1. Newest row fresh, marker stale, reload fixes it, and it recurs after minutes. Transport: heartbeat, backoff, snapshot on reconnect.
  2. Newest row fresh, marker stale, reload fixes it and it does not recur. The tab was backgrounded. Resync on visibility change.
  3. Newest row fresh, marker stale, reload does not fix it, tab at high CPU. Rendering: mutate markers, coalesce updates, cluster.
  4. Newest row fresh, all markers stale, no socket open at all, and the server is healthy. Subscription or authentication failed silently on connect — check the server's view of active subscribers.
  5. Newest row stale for every vehicle. Ingest: consumer lag, then write batching, then cadence.
  6. Newest row stale for some vehicles only. Not this page. Go to the per-vehicle staleness investigation, which is an install, SIM and backfill problem.

Most of this is an afternoon of work done in advance: an age on every marker, a connection indicator, a heartbeat, a snapshot on reconnect. Building those in from the start rather than after the first frozen morning is the difference between a dispatch screen people trust and one they check by phone — the kind of thing we scope explicitly in MVP and product builds. Adjacent diagnoses sit in telematics and the live vehicle data plane, inside our logistics and mobility work.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Why are vehicles not updating on our live fleet map?

In most fleet-wide freezes the data is arriving and the screen is not receiving it. Compare the newest position row's server receipt time against the age the marker shows: if the row is seconds old, the fault is a dropped connection with no reconnect, a reconnect with no resync, or a rendering path that cannot keep up. Only when the newest row is genuinely old does the ingest path need attention.

Why does the map fix itself when I reload the page?

Because a reload creates a fresh connection and fetches current state, which is exactly what the failed reconnect should have done. It confirms the transport, not the data. The permanent repair is a heartbeat that detects a dead connection within a minute, reconnection with backoff and jitter, and a snapshot request on reconnect so the map does not wait for each vehicle to ping.

How many vehicles can a browser map show before it slows down?

With individually styled marker elements, problems usually start in the low hundreds in view, and the exact number depends on marker complexity, update rate and the machine. Measure it on the oldest machine in the dispatch office. Two changes move the ceiling: update existing markers instead of recreating them, and stream only vehicles inside the current map bounds.

Does a background browser tab stop the live map updating?

Yes. Browsers clamp timers in background tabs to roughly once a minute and suspend animation callbacks entirely, so a map behind another window is not refreshing on the schedule you configured. Listen for the visibility change event, resync on return, and display the age of every position so a dispatcher sees that a marker is 4 minutes old.

  • live map
  • telematics
  • frontend performance
  • debugging
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Read next

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation