Quick Answer
A fleet tracking backend should treat every GPS ping as untrusted input. Sort pings by device time, drop duplicates and impossible values, reject poor fixes and teleport jumps, hold position while a vehicle is parked, and add hysteresis to geofences. Keep the raw stream, store the cleaned stream beside it, and snap to roads only after cleaning. The Python below was tested on synthetic data only, not on live device feeds.
Why does a fleet app receive bad GPS data?
Some of the reasons are written down in vendor documentation. Samsara's vehicle locations documentation says a device reports about every 5 seconds while the vehicle is on and about once an hour while it is off. It also says identical consecutive records can occur, and that GPS interference in a garage can suppress updates even when the vehicle shows as on. The same page says the device keeps a rolling 30 days of location data, so after a connection is restored the buffered points become available through the API.
Read together, those statements describe four problems a backend must expect: duplicate rows, silent gaps, a misleading "on" status, and late data that arrives out of order. This is one vendor's documentation. Other vendors will behave differently, so read the equivalent page for the device you actually use.
What should the ingest layer check before it stores a ping?
My suggestion (author judgement, not a standard) is six cheap checks, run in this order:
- Sort by device timestamp, so late arrivals land in the right place.
- Drop exact duplicates (same time and position).
- Reject impossible values, including out-of-range coordinates and the 0,0 position that some receivers report before they have a fix.
- Reject poor fixes, where the reported accuracy is worse than a threshold.
- Reject teleport jumps, where the implied speed between two kept points is not plausible for a vehicle.
- Hold position while parked, so receiver jitter does not draw a wandering trail.
The thresholds in the code (50 m accuracy, 45 m/s, 10 m jitter) are starting values I chose for the example. Tune them against your own vehicles and devices.
from dataclasses import dataclass
from math import radians, sin, cos, asin, sqrt
@dataclass(frozen=True)
class Ping:
device: str
ts: int # epoch seconds, device clock
lat: float
lon: float
acc_m: float = 10 # reported horizontal accuracy in metres
def haversine_m(a, b):
r = 6371000.0
p1, p2 = radians(a.lat), radians(b.lat)
dp, dl = p2 - p1, radians(b.lon - a.lon)
h = sin(dp / 2) ** 2 + cos(p1) * cos(p2) * sin(dl / 2) ** 2
return 2 * r * asin(sqrt(h))
def clean(pings, max_acc_m=50, max_speed_ms=45, jitter_m=10):
"""Return a cleaned, time-ordered list for ONE device."""
seen, ordered = set(),
[] for p in sorted(pings, key=lambda p: p.ts): # 1. fix ordering
key = (p.ts, round(p.lat, 6), round(p.lon, 6))
if key in seen: # 2. drop duplicates
continue
seen.add(key)
if not (-90 <= p.lat <= 90 and -180 <= p.lon <= 180): # 3. impossible values
continue
if p.lat == 0 and p.lon == 0: # "null island" fix
continue
if p.acc_m > max_acc_m: # 4. poor fix
continue
ordered.append(p)
out =
[] for p in ordered:
if out:
prev, dt = out[-1], p.ts - out[-1].ts
if dt <= 0:
continue
d = haversine_m(prev, p)
if d / dt > max_speed_ms: # 5. teleport jump
continue
if d < max(jitter_m, p.acc_m): # 6. parked jitter
p = Ping(p.device, p.ts, prev.lat, prev.lon, p.acc_m)
out.append(p)
return out
Testing status: I ran six unit tests with Python 3.13 on synthetic points: out-of-order input, duplicates, 0,0 and poor-accuracy points, a teleport jump, parked jitter, and geofence flapping. All six passed. I have not run this against real device feeds, so treat it as a teaching sample and not production code.
How do you stop geofence alerts from flapping?
A vehicle parked near the edge of a depot boundary can cross it back and forth because of receiver noise, and each crossing can fire an alert. Two techniques help. Use hysteresis, which means the vehicle enters a zone inside radius r but only exits beyond r plus a buffer. Then require several consecutive pings before the state changes.
class Geofence:
"""Circle fence with hysteresis: enter inside r, exit only outside r + buffer."""
def __init__(self, lat, lon, r_m, buffer_m=30, confirm=2):
self.c = Ping("fence", 0, lat, lon)
self.r, self.buf, self.confirm = r_m, buffer_m, confirm
self.inside, self._streak = False, 0
def update(self, p):
d = haversine_m(self.c, p)
want_inside = d <= self.r if not self.inside else d <= self.r + self.buf
if want_inside == self.inside:
self._streak = 0
return None
self._streak += 1
if self._streak >= self.confirm:
self.inside, self._streak = want_inside, 0
return "enter" if self.inside else "exit"
return None
In the test, a sequence of distances of 150, 90, 95, 110, 98, 105, 160 and 170 metres from a 100 m fence produced exactly one enter event and one exit event. Two of those readings (110 m and 105 m) were outside the 100 m radius while the vehicle was still inside the zone, and the buffer absorbed both.
Should you snap points to roads?
Map matching can clean what the filters above leave behind, but it has its own rules. Google's Roads API documentation says one snap-to-roads request accepts up to 100 GPS points and returns points snapped to the most likely road. It recommends keeping consecutive points at or below about 300 metres apart, and offers an optional interpolate setting that adds points following the road shape. Interpolated points have no original index, so the response can contain more points than the request.
OSRM's Match service takes optional timestamps, which must increase, and optional per-point radiuses that default to 5 metres. The documentation suggests using the device's reported accuracy. It returns null for points dropped as outliers and a confidence score from 0 to 1 for each matching. The OSRM page I read was for version 5.5.1, so check the documentation for the version you run.
My judgement: snap after cleaning, keep the raw point and the snapped point side by side, and treat a low confidence score as a flag for review rather than an error.
How do you find vehicles near a depot quickly?
PostGIS documents ST_DWithin as a cheap filter that can use a spatial index, while ST_Distance computes exact distances and cannot use indexes. For geography values the distance is in metres. The common pattern is to filter with ST_DWithin first and sort with ST_Distance on what remains.
SELECT v.id, ST_Distance(v.last_position, d.location) AS metres
FROM vehicles v
JOIN depots d ON d.id = 7
WHERE ST_DWithin(v.last_position, d.location, 2000)
ORDER BY metres;
This query is untested. It assumes both columns are geography with a spatial index on last_position, so check the types and the index in your own schema.
What should the fleet database store?
In my view three tables cover most needs: an append-only table of raw pings, a table of cleaned pings that maps and reports read, and a small table holding the last known position per vehicle for proximity queries. Keeping the raw data lets you re-run a better filter later and settle disputes about a route.
Which are the top five fleet management app development companies?
Teams that prefer to buy this work instead of building it can compare the five partners below. The list is not a ranking of quality.
Figures below come from each company's own website and are self-reported, so confirm them directly before signing anything.
1. Dev Technosys
Dev Technosys is a fleet management app development company with 250+ professionals that does business globally. Its fleet page describes connecting GPS tracking, fuel monitoring and dispatching systems, then automating assignments, maintenance alerts and journey updates. The company builds its own platforms and connects them to existing business systems through APIs instead of configuring third-party ERP products. It states an 89% project success rate and says most new business comes through client referrals; both claims are self-reported. That scope fits teams that already own tracking hardware and need workflow software around it.
2. N-iX
N-iX lists fleet management software development as a dedicated service. Its page covers telematics and predictive-maintenance integration, ELD and IoT sensor integration, hours-of-service compliance modules, route-planning and dispatch engines, and mobile fleet apps. A case study describes a GPS-tracked in-vehicle Linux gateway, a Google Cloud IoT platform and an Android driver app for a telematics client, in a partnership that began in February 2021. The site states over 2,400 software engineers, and the case study gives no fleet outcome figures. N-iX suits teams that need hardware-to-cloud telematics work from one vendor.
3. Intellias
Two fleet case studies sit on the Intellias site. In the first, a Florida telematics client has worked with the company since 2018 on a platform with real-time GPS mapping, idle-time tracking and diagnostic trouble code reporting, and the page says it handles 100,000+ vehicles with data points every 30 seconds. The second is a native iOS, Android and Angular truck-tracking front end for a large car maker, tested on 1,000 vehicles and offered in more than 20 countries. Intellias suits teams that expect high vehicle counts and need a backend built for that volume.
4. Altoros
Altoros says it was founded in 2001 and lists GPS tracking software for car rental, trucking and delivery, fleet management with vehicle tracking and dispatch, and IoT platforms for fleets. Its logistics page cites a transport management case serving 100+ companies and processing 10,000+ automated orders a day, with operator workload cut by up to 70%, plus a truck-parking app prototype covering 10,000+ locations. All of these figures are self-reported, and the page names no ISO certification, so ask for evidence. Altoros suits teams that want an IoT-heavy build from a long-established vendor.
5. STX Next
Describing itself as a Python-native team with more than 20 years of experience, STX Next lists fleet management systems, route optimization, electronic proof of delivery, predictive maintenance and IoT integration on its transport and logistics page. Named case studies include Sendcloud (a carrier integration proof of concept), GS1 Polska (a location-data app for drivers) and T Dispatch (dispatch software). The page mentions Python, IoT, RFID, AWS, Azure and Snowflake and lists delivery centers in Poznan and Merida, but it states no headcount. STX Next suits teams that prefer a Python backend.
FAQ
How often should a fleet device send a position?
Samsara's documentation describes about every 5 seconds while a vehicle is on and about hourly while it is off. Your hardware and data plan set the real figure.
Should raw pings be deleted after cleaning?
In my view, no. Keep them for a retention period your own policy allows, so you can re-run improved filters later.
Do I need map matching in every fleet app?
No. Many dashboards work with cleaned points. Matching helps most when you report distance driven on roads.
What accuracy threshold should I use?
The example uses 50 m as a starting value. Tune it per vehicle type and device.
Can I use this code in production?
It is a teaching sample tested on synthetic data. Add tests built from real device samples first.#python #backend #iot #architecture #software #coding #development #engineering #inclusive #community
Designing a Fleet Tracking Backend That Handles Bad GPS Data