When you load a GPX route into PitStopper today, something invisible starts happening. After a couple of quiet seconds - while you're reading the route stats or taking a look at the elevation profile - the app is working in the background, fetching all ~70 built-in POI categories along your entire route. By the time you want to tick a category, it's already there. No network, no wait.
What changed
Before, each POI category was a network request - click "Water" on your route, and the app queried the PostGIS server for fountains and springs. Tick "Cafes" and made another. With 20 categories selected that's 20 queries, and on a long route they added up. Fast? Sure - the PostGIS engine answers each one in under a second. But still a cost.
Now, those queries happen once, in the background, within ~2-3 seconds of the route loading. We fetch at a fixed 1km radius (double the default 500m search radius), store everything in the browser cache, and by the time you're ready to search, the answer is sitting locally. Tick any category - instant. Slide the radius up to 500m, 750m, 1000m - all instant, because the cache already holds everything up to 1km. Slide past that and a quick hint appears asking for a fresh search; you search, and the cache grows. Save the route as a project and all that prefetched data is baked into the .psp file - open it later and it opens fully warm.
How the trick works
Long routes posed a challenge: a single giant query for the entire route and all categories would time out. Our solution was the one from the PostGIS engine itself - split the route into ~150 km segments, fetch each segment for all categories in parallel, then deduplicate by OpenStreetMap id. The mathematical neat part: a corridor around a route equals the union of corridors around its segments at their shared points. So the chunked approach returns exactly the same POIs as one giant query, with no seams and no duplicates.
Speculative work has to be polite - about your attention, and about other people's servers. The prefetch talks only to our own POI server: if it's unavailable, there's simply no prefetch (your searches are unaffected and keep their normal fallbacks). If a prefetch fails part-way, it stops silently - no error message, no retry storm, no escalation. And the instant you click "Search", it cancels and stands down so your actual query is never competing with it.
No enrichment happens in the background. Elevation for POIs, food-hygiene ratings, fuel prices - those still load on demand when you tick the category. Prefetch is just the stubborn geometry: location, name, OpenStreetMap id.
Custom user-defined categories skip the prefetch entirely - they're defined by OSM tags you picked yourself, and there's no sensible way to predict what you'll ask for. They search on demand and cache like everything else.
The feature disappears on data-saver connections, already-warm project loads, and location-mode searches (where "prefetch all categories at 1km" makes no sense).
The measured reality
Tests on our server (p.pitstopper.net, launched the same day) show that a prefetch of all ~70 categories along a typical day-ride route (81 km) takes about 0.74 s total - server returns the data in ~0.37 s. A 20-category subset on a 180 km route runs in 0.31 s server + overhead. Long routes chunk into a few ~1 s slices. So the invisible work that used to cost you a per-search network roundtrip now happens once, silently, in the background.
What this unlocks
The radius slider, which was always a network control (change it, and you'd refetch), is now purely local up to 1km. Cycling tours, bikepacking, hiking trips - you can explore "what else is out there" without waiting. Saved projects truly are saved - they open instantly, fully ready.
The predicted counts feature (the dimmed ≈N estimates that told you "there are roughly 47 restaurants along this route") was our early scout. The prefetch is the quiet bulk delivery of the substance behind those numbers.
The sequel we couldn't resist
Once every POI along your route lives in the browser, an obvious question appears: why can't I just search it? So we built that too. Tools → Search Route takes a name or brand - "Tesco", "Greggs", the name of that campsite someone mentioned - and shows every match within 1km of your route as you type, ranked by how well it matches and how far along the route it sits. No network request; it's a lookup over data you already have, so it works in a dead spot on a hillside just as well as at home.
Each result can be expanded for its details (opening hours, address, what OpenStreetMap knows) or added straight to the map with one tap - and an added POI is pinned: it stays visible even if you never tick its category, survives new searches, and saves into your project. The modal also tells you what it's searching: something like "1,890 POIs cached along your route (1 km each side) in 47 categories" - the prefetch's haul, itemised.
The prequel
This feature rides on the PostGIS engine we shipped earlier ("POI Searches Just Got Up To 20× Faster") - that's what made speculative work affordable in the first place. The engine reduced search cost from ~10-20 seconds on a long route to ~0.7 seconds. Without that foundation, prefetch would be noise. With it, prefetch turns the app from "search when you need to know" to "you already know" - which changes the feel.


