Building Location-Aware Applications
Location data powers a surprising range of business applications. Delivery routing. Territory management. Asset tracking. Store locators. Service area definition. Field workforce coordination. Property map search for estate agents. Planning boundary queries for local authorities. Anywhere geography matters to operations, location-aware applications provide value. These features integrate naturally with web applications and mobile apps, adding spatial awareness to core business workflows.
The naive implementation is straightforward: store latitude and longitude as decimals, call Google Maps when you need a map, and use the Haversine formula for distance calculations. This works for a proof of concept. It breaks in production when you need to query "find all customers within 15km of this warehouse" against 50,000 records. It also breaks when your geocoding bill arrives, or when users in rural areas complain that addresses aren't resolving correctly.
Building location features that perform at scale, cost predictably, and handle edge cases requires understanding the full stack. That means coordinate systems, geocoding strategies, spatial databases, map rendering, routing optimisation, and the privacy implications of location data. This page covers the patterns we use across logistics, field service, retail, fleet management, and property applications.
Coordinate Systems and Precision
Coordinates look simple. Latitude and longitude, two numbers. The complexity hides in the details.
WGS84: The Standard
WGS84 (World Geodetic System 1984) is the coordinate reference system used by GPS and most mapping services. Coordinates are expressed as latitude (north/south, -90 to +90) and longitude (east/west, -180 to +180). Store coordinates in this format unless you have a specific reason not to.
Some legacy systems use other coordinate systems. British National Grid (EPSG:27700) is common in UK government data, including Ordnance Survey datasets and local authority planning systems. UTM (Universal Transverse Mercator) appears in surveying data. PostGIS handles conversions between systems using ST_Transform, so you can ingest EPSG:27700 data from OS sources and convert on import: ST_Transform(geom, 4326) converts British National Grid to WGS84.
Precision Matters
Coordinate precision directly affects accuracy. Each decimal place represents roughly:
| Decimal Places | Approximate Precision | Use Case |
|---|---|---|
| 1 | ~11 km | Country-level only |
| 2 | ~1.1 km | Town identification |
| 3 | ~110 m | Street-level |
| 4 | ~11 m | Building identification |
| 5 | ~1.1 m | Door-level accuracy |
| 6 | ~10 cm | Survey-grade positioning |
For most business applications, 6 decimal places is sufficient. Storing more precision wastes space without adding useful accuracy (GPS itself is typically accurate to 3-5 metres under normal conditions).
Storage format: Store coordinates as DECIMAL(9,6) for latitude and DECIMAL(10,6) for longitude if using standard SQL columns. This accommodates the full range of valid coordinates with appropriate precision. Better still, use PostGIS geometry types.
The Earth Is Not Flat
The Haversine formula calculates the great-circle distance between two points on a sphere. It is computationally cheap and accurate enough for most purposes. For distances under 20km, the error from assuming a perfect sphere is negligible.
For longer distances or when accuracy matters (surveying, precise routing), use the Vincenty formula or PostGIS's geography type, which accounts for the Earth's ellipsoidal shape. The difference between spherical and ellipsoidal calculations can be up to 0.5% over long distances.
Geocoding: Addresses to Coordinates
Converting addresses to coordinates (forward geocoding) and coordinates to addresses (reverse geocoding) is fundamental. It's also where naive implementations become expensive.
The Naive Approach
Call a geocoding API every time you need coordinates. Google Maps Geocoding API, Mapbox, or HERE. Pass the address string, get back latitude and longitude.
This works until:
- You process a bulk import of 10,000 customer addresses and the API bill arrives
- The API rate-limits you mid-import and the job fails
- Users experience latency spikes during address entry
- The same addresses get geocoded repeatedly across different features
The Robust Pattern: Geocode on Write, Cache Aggressively
The principle is simple: geocode addresses at the point of entry (import, user submission, CRM update), store the result, and avoid re-geocoding the same address at read time. Coordinates change when buildings are demolished, not when a user loads a page. Pre-geocoding at write time eliminates per-request API costs and latency entirely. Note: some providers (notably Google) restrict how long you can cache results and require periodic re-validation. Check your provider's terms of service for caching rules before implementing. This requires:
Address Normalisation
Before geocoding, normalise addresses to a canonical form. "10 Downing Street, London" and "10 Downing St, London, UK" should resolve to the same cache key. Strip whitespace, standardise abbreviations, uppercase for comparison. This prevents duplicate geocoding of equivalent addresses.
Geocode Results Table
Store geocoded results with the normalised address as key, coordinates, provider used, confidence score, and timestamp. Index on the normalised address for fast lookups. Include the raw API response for debugging.
Batch Processing
Queue geocoding jobs for bulk imports rather than processing synchronously. Respect API rate limits. Retry failed geocodes with exponential backoff. Alert on systematic failures, which often indicate address data quality issues rather than API problems. For reliable queue handling patterns, see our approach to background jobs.
Provider Selection
Geocoding providers vary significantly in accuracy, coverage, and cost.
| Provider | Strengths | Considerations |
|---|---|---|
| Google Maps | Excellent global coverage, high accuracy, address autocomplete | Most expensive, strict attribution requirements |
| Mapbox | Good accuracy, generous free tier, flexible terms | Weaker in some regions, less detailed POI data |
| HERE | Strong European coverage, good batch processing, enterprise support | Complex pricing, heavier API |
| Nominatim (OSM) | Free and self-hostable, open data | Variable accuracy, limited commercial support. The public instance has strict usage policies (max 1 req/sec, no bulk use, no heavy crawling); self-hosting removes those limits |
| Postcodes.io (UK) | Free UK postcode lookups, fast, no rate limits | UK only, postcode centroid (not door-level) |
For UK-focused applications, a hybrid approach works well. Use Postcodes.io for initial postcode-based lookups (free, fast), then fall back to Google or Mapbox for full address resolution when door-level precision is needed.
UK-Specific Data Sources
Global geocoding providers miss nuances in UK address data. Several UK-specific sources fill the gaps:
- Ordnance Survey Data Hub: AddressBase provides authoritative UK address data with UPRN (Unique Property Reference Number), the canonical identifier for every addressable location in Great Britain. OS Maps API and OS Features API offer high-quality UK mapping. Commercial licensing costs apply, but the data quality for UK addresses exceeds any global provider.
- Royal Mail PAF: The Postcode Address File validates UK postal addresses. Useful for address entry validation and normalisation, though it requires a licence.
- what3words: Divides the world into 3m squares, each with a three-word address. Adopted by UK emergency services. Useful for locations without traditional addresses (rural sites, event spaces, construction sites). API costs per lookup.
- UPRN: The Unique Property Reference Number is the gold standard for UK address matching. If your application deals with UK property data, planning, or utilities, storing UPRNs alongside coordinates prevents the duplicate-address problems that plague postcode-only systems.
UK addresses also present specific normalisation challenges. Welsh locality names with diacritics, Scottish address structures that confuse global parsers, rural house names without street numbers, and new-build postcodes that lag behind in provider databases all cause problems. Test your geocoding against these edge cases early.
Address Autocomplete
Address autocomplete provides suggestions as users type, reducing errors and improving data quality. Google Places Autocomplete is the standard, but charges per session (a session covers all keystrokes until selection).
Implementation pattern: debounce input (wait 300ms after typing stops before querying), restrict to relevant countries, bias results toward user location, and validate the final selected address with a geocode call.
Terms of service: Google requires proper attribution when displaying Places Autocomplete results, though they do not have to appear on a Google Map. If you are using Mapbox or Leaflet for display, check the current Places API terms for attribution requirements. Mapbox and Algolia Places offer alternatives with more flexible terms.
Geocoding sits at the boundary between your application and external services. The same patterns that apply to any API integration apply here: rate limiting, retry logic, circuit breakers for provider outages, and fallback chains when a primary provider returns low-confidence results.
Spatial Databases: PostGIS
Storing coordinates as decimal columns works for simple cases. Once you need to answer questions like "find all locations within 10km" or "which delivery zone contains this address", you need a spatial database.
The Naive Approach
Store latitude and longitude as decimals. Calculate distances in application code. For "find nearest", pull all records and sort by calculated distance.
This fails at scale. Calculating distance for 50,000 records takes seconds. The database can't use indexes for distance queries because the calculation happens after retrieval. Memory usage spikes when loading all records for in-application filtering.
The Robust Pattern: PostGIS
PostGIS extends PostgreSQL with spatial types and functions. Coordinates become geometry or geography objects. Spatial indexes enable fast queries against millions of records.
Geometry vs Geography Types
PostGIS offers two spatial types with different calculation methods:
geometry
Planar calculations (flat Earth). Faster. Suitable for small areas where curvature is negligible. Units depend on coordinate system (degrees for WGS84).
Use for: building floor plans, city-scale analysis, when performance matters more than precision.
geography
Spheroidal calculations (curved Earth). Slower but accurate over long distances. Results in metres. Automatically handles coordinate wrapping.
Use for: country-wide queries, international applications, when accuracy matters.
For most business applications, geography is the better default. The performance difference is measurable but rarely significant with proper indexing.
Essential Spatial Queries
PostGIS provides functions for common spatial operations:
ST_DWithin: Find Within Distance
SELECT * FROM locations WHERE ST_DWithin(location, ST_MakePoint(-0.1276, 51.5074)::geography, 10000)
Returns all locations within 10km of the given point. Uses spatial indexes. Fast even against millions of records.
ST_Distance: Calculate Distance
SELECT name, ST_Distance(location, ST_MakePoint(-0.1276, 51.5074)::geography) as distance FROM locations ORDER BY distance LIMIT 10
Returns the 10 nearest locations with exact distances in metres. Combine with ST_DWithin for performance (filter first, then calculate exact distances).
ST_Contains / ST_Covers: Point in Polygon
SELECT zone.name FROM delivery_zones zone WHERE ST_Covers(zone.boundary, ST_MakePoint(-0.1276, 51.5074)::geometry)
Returns which delivery zone contains the given point. Essential for territory assignment and service area checks. Prefer ST_Covers over ST_Contains for zone checks: ST_Covers includes points exactly on the boundary, so addresses on a zone edge are included rather than excluded.
ST_Intersects: Overlap Detection
SELECT a.name, b.name FROM territories a, territories b WHERE a.id != b.id AND ST_Intersects(a.boundary, b.boundary)
Finds overlapping territories. Useful for validation and conflict detection.
Spatial Indexing
Spatial indexes (GiST or SP-GiST) are essential for performance. Without them, every spatial query scans the entire table. With them, PostGIS can eliminate most records before calculation.
CREATE INDEX idx_locations_geom ON locations USING GIST (location);
PostGIS does not create spatial indexes automatically. You must create them explicitly, and verify with EXPLAIN ANALYZE that your queries are using the index. When setting up spatial columns through database migrations, include the GiST index in the same migration as the column creation. Forgetting the index is the single most common PostGIS performance mistake.
Performance benchmark: A "find within 10km" query against 100,000 points completes in under 10ms with a spatial index. Without the index, the same query takes 2-3 seconds. Index your spatial columns.
GeoJSON: The Interchange Format
GeoJSON (RFC 7946) is the standard format for exchanging spatial data between server and client. PostGIS converts to and from GeoJSON natively with ST_AsGeoJSON and ST_GeomFromGeoJSON. All major map libraries (Mapbox GL JS, Leaflet, MapLibre) consume GeoJSON directly.
For your API endpoints, return GeoJSON FeatureCollections. This keeps your spatial data interoperable: the same endpoint can feed a web map, a mobile app, or a data export. For large datasets, consider streaming GeoJSON or converting to vector tiles with Tippecanoe instead.
ORM Integration
The bridge between PostGIS and application code is where many implementations stall. Raw SQL spatial queries work, but they bypass your ORM's query builder, making code harder to test and maintain.
In Laravel, packages like laravel-postgis add spatial column types to migrations and Eloquent model casts for geography types. Define query scopes for common spatial operations (scopeWithinDistance, scopeInZone) so the rest of your application works with familiar Eloquent syntax. The underlying SQL uses PostGIS functions, but application code reads cleanly. Good data modelling matters here: separate your spatial concerns (a locations table with geography columns and spatial indexes) from your business entities, joined by foreign key.
Map Display and Rendering
Map display seems straightforward: embed a map, add markers. The complexity emerges with scale (thousands of markers), customisation requirements, and mobile performance.
Provider Options
The mapping library you choose affects performance, cost, and how much control you have over styling. Each option sits at a different point on the trade-off between convenience and flexibility.
| Provider | Type | Best For |
|---|---|---|
| Google Maps | Proprietary | Consumer-facing apps where users expect Google. Street View. Places data. |
| Mapbox GL JS | Vector tiles | Custom styling, high performance, data visualisation. Developer-friendly. |
| Leaflet | Library (tile-agnostic) | Lightweight, works with any tile provider. Good for simple maps. |
| OpenLayers | Library (tile-agnostic) | Complex GIS applications. Steeper learning curve, more capable. |
| Maplibre GL JS | Vector tiles (open source) | Mapbox GL fork, no vendor lock-in, self-hostable. |
For internal business applications, Mapbox GL JS or Maplibre typically offer the best balance of capability and cost. For consumer applications where users expect familiar UI, Google Maps may be worth the premium. For applications requiring 3D terrain, globe visualisation, or spatial data overlaid on geography, see our work on geospatial and globe visualisation with Three.js.
Raster vs Vector Tiles
Traditional maps use raster tiles: pre-rendered images at each zoom level. Vector tiles send raw geometry data and render on the client.
Vector tiles are the modern standard. Use raster only when supporting legacy devices or when map styling isn't needed.
Handling Many Markers
Displaying thousands of markers causes performance problems. The browser struggles to render them all, and the map becomes unusable visually.
Marker Clustering
Group nearby markers into clusters that show a count. Expand on zoom or click. Leaflet.markercluster and Mapbox's cluster sources handle this automatically. For 10,000+ points, server-side clustering (PostGIS ST_ClusterKMeans) before sending data to the client improves initial load.
Viewport Loading
Only load markers visible in the current viewport. As the user pans or zooms, fetch new data. Requires a spatial query backend (PostGIS) that can efficiently return points within the current bounding box using ST_MakeEnvelope. Include a buffer around the viewport to prevent flickering during pan.
Vector Tile Data Layers
For very large datasets (100,000+ points), generate vector tiles from your data. Tippecanoe (from Mapbox) converts GeoJSON to vector tiles. Serve from a tile server as static files or generate dynamically on request. The map library handles rendering efficiently using WebGL.
Performance target: Map interactions (pan, zoom) should feel instant, under 100ms. If your map stutters, you're sending too much data to the client. Move filtering and aggregation to the server.
When to Level Up
Most location features start simple and grow. The trick is recognising the breakpoints where your current approach stops working and the next level of infrastructure becomes necessary.
| Trigger | Current Approach | Upgrade To |
|---|---|---|
| 1,000+ location records | DECIMAL lat/lng columns, distance calc in application code | PostGIS geography columns with GiST indexes |
| 500+ geocoding requests/month | Geocode on every request | Cache-once architecture with normalised address keys |
| 500+ map markers | Render all markers on load | Client-side clustering (Leaflet.markercluster, Mapbox clusters) |
| 10,000+ map markers | Client-side clustering | Server-side clustering (ST_ClusterKMeans) or vector tile generation |
| 10+ delivery stops | Nearest-neighbour heuristic | Google OR-Tools or commercial VRP solver |
| Field apps in rural areas | Online-only map and data access | Offline tile caching, local database, queue-and-sync |
Each upgrade adds complexity but solves a real operational problem. The cost of upgrading too early is wasted engineering. The cost of upgrading too late is a broken production system. Watch your record counts, API bills, and user complaints for the signals.
Routing and Optimisation
Simple directions (A to B) are a solved problem. Multi-stop route optimisation with constraints is computationally hard and remains an active area of development.
Directions APIs
All major providers offer directions APIs: Google Directions, Mapbox Directions, HERE Routing, OSRM (open source). They return distance, duration, and turn-by-turn instructions for a given origin and destination. For multi-stop problems, pre-computing a distance matrix between all pairs of stops avoids redundant API calls during optimisation.
Considerations when choosing:
- Traffic data: Google and HERE have the best real-time traffic. Mapbox and OSRM use historical patterns.
- Vehicle profiles: Truck routing needs height, weight, and hazmat restrictions. Not all providers support this.
- Waypoints: Most APIs support intermediate stops but limit the number (Google: 25 waypoints).
- Terms: Google requires displaying routes on Google Maps. Others are more flexible.
The Route Optimisation Problem
Given a set of stops, find the order that minimises total distance or time. This is the Travelling Salesman Problem (TSP), which is NP-hard. Exact solutions are computationally infeasible beyond about 20 stops.
Practical Approaches
Since exact answers are infeasible at scale, practical routing relies on heuristics and solver libraries that find good-enough routes within time constraints.
Nearest Neighbour Heuristic
Start at the depot, always go to the nearest unvisited stop. Fast (O(n^2)), easy to implement, produces routes 20-25% longer than optimal. Good enough for informal route suggestions.
Google OR-Tools
Open-source optimisation library from Google. OR-Tools handles TSP, Vehicle Routing Problem (VRP), and variants with time windows, capacity constraints, and multiple vehicles. Python and C++ interfaces. Production-grade for medium-scale problems (hundreds of stops).
Commercial Optimisation APIs
Google Route Optimization API, Mapbox Optimization API, HERE Tour Planning. Handle large-scale problems, include traffic, return turn-by-turn directions. Cost scales with stops and complexity.
Constraints in Real Routing
Real delivery and service routing involves constraints that basic TSP ignores:
- Time windows: Customer available 9am-12pm only. Delivery before 6pm.
- Vehicle capacity: Van holds 50 packages or 500kg.
- Driver hours: Maximum 8 hours driving. Mandatory breaks.
- Priority stops: Some stops must happen first or last.
- Skills: Some deliveries require specific equipment or certification.
- Return to depot: Or end at a different location.
Each constraint narrows the solution space but complicates the optimisation. Commercial APIs and OR-Tools support these constraints; naive implementations don't. For automated dispatch and job assignment, route optimisation often integrates with a workflow engine that handles the business rules around assignment, escalation, and rescheduling.
Real-world result: A logistics client reduced daily route distance by 18% after implementing constraint-aware optimisation. For a fleet of 12 vehicles, this translated to measurable fuel savings and an extra 2-3 deliveries per vehicle per day.
Offline Maps and Caching
Field applications often operate where connectivity is poor or absent. Offline capability requires caching both map tiles and application data.
Map Tile Caching
Map tiles can be cached locally for offline use. The approach depends on the platform:
Mobile Native
Mapbox Mobile SDKs support offline map packs. Define a region and zoom range, download in advance. Tiles stored in SQLite. Automatic management of cache size and expiry.
Progressive Web Apps
Service workers can cache tile requests. Limited storage (varies by browser, typically 50-100MB usable). Manual cache management needed. Consider caching only frequently-accessed areas.
Desktop/Embedded
Download tile sets directly. MBTiles format (SQLite) is standard. Leaflet and OpenLayers support local tile sources. Storage is less constrained; pre-cache entire regions.
Terms of Service
Tile caching terms vary significantly by provider:
- Google Maps: No caching permitted beyond browser/OS cache. Offline requires specific licensing.
- Mapbox: Offline supported in mobile SDKs with active subscription. Pre-rendering for distribution requires custom agreement.
- OpenStreetMap: Free to cache and distribute. Attribution required.
For applications requiring offline maps, OSM-based tiles (self-hosted or via providers like Mapbox with appropriate licensing) are often the most practical choice.
Offline Data Synchronisation
Caching map tiles is only half the problem. Application data (customer locations, job details, route information) also needs offline access with eventual synchronisation. This is where offline-first architecture gets genuinely hard.
Patterns for offline data:
- Download before departure: Sync the day's jobs before leaving. Read-only offline access.
- Queue modifications: Store changes locally, sync when connectivity returns. Handle conflicts (same record modified by different users).
- Optimistic UI: Show success immediately, sync in background. Roll back if sync fails.
Implementation note: For React Native and Expo applications, WatermelonDB provides a reliable local database with sync capabilities. For web PWAs, IndexedDB with a sync layer handles most cases. The complexity is in conflict resolution, not storage.
Geofencing
Geofencing triggers actions when a device enters or exits a defined geographic area. Common uses: delivery arrival notifications, time tracking for field workers, asset security alerts.
Implementation Approaches
Geofencing can run on the device or on the server. The right choice depends on whether you control the app, how many fences you need, and whether position data is already flowing to a backend.
Client-Side (Mobile OS)
iOS and Android provide native geofencing APIs. Define regions, receive callbacks on entry/exit. Battery-efficient (uses cell towers and WiFi, not continuous GPS). Limited to 20 monitored regions per app on iOS.
Best for: user's own device, where you control the app.
Server-Side
Device reports location periodically. Server checks position against fence definitions using PostGIS ST_Contains. More flexible (unlimited fences, complex shapes), but requires position reporting infrastructure.
Best for: fleet tracking, asset monitoring, where position is already being reported.
Fence Definition
Circular fences (centre point plus radius) are simplest. Polygonal fences allow arbitrary shapes (property boundaries, irregular service area boundaries). PostGIS handles both.
For client-side geofencing, circular regions are more battery-efficient. For server-side, polygons add no cost.
Edge Cases and Practical Thresholds
- GPS jitter: Position updates can bounce in and out of a fence boundary. Implement hysteresis (require position to be clearly inside/outside before triggering, typically 20% of fence radius) and debounce events (30 seconds is a sensible default before confirming entry/exit).
- Tunnel/building entry: GPS signal loss can look like an exit. Don't trigger alerts on signal loss alone. Require multiple consecutive position reports outside the fence before confirming exit.
- Minimum fence radius: GPS accuracy (3-5m open sky, 10-30m in urban canyons) limits useful minimum fence size. A 10m fence will generate false triggers. Use 50m minimum for outdoor fences, 200m in dense urban areas.
- iOS region limit: iOS caps monitored regions at 20 per app. For applications with more fences, use server-side geofencing with PostGIS, or dynamically register the nearest fences based on the device's current position.
Geofencing reliability depends on treating GPS as an approximate, noisy signal rather than a precise measurement. Every fence implementation needs a state machine with clear transitions between outside, entering, inside, and exiting states. Each state should have defined thresholds before the transition confirms.
Privacy and Compliance
Location data is personal data under GDPR and similar regulations. Collection, storage, and processing require appropriate legal basis and security measures.
Legal Basis
For employee location tracking, legitimate interest may apply for delivery tracking (customers expect to know where their package is) but consent is typically required for broader monitoring. The ICO's guidance on monitoring workers sets out specific requirements for location tracking of employees. For consumer applications, consent is almost always required.
The legal basis affects what you can do with the data. Purpose limitation is strict: location collected for delivery tracking cannot be repurposed for productivity monitoring without separate consent and a separate legal basis. This distinction matters in practice, because the same GPS data could serve both purposes.
Data Minimisation
Collect only what's needed. Store only what's needed. Delete when no longer needed.
Transparency
Users should know when location is being collected and why. Mobile apps should use location permission prompts that explain the purpose. Employees should have clear policies on what's tracked and how it's used.
Consider providing users access to their own location history. This builds trust and is often required under data subject access rights.
Security
Location data reveals patterns: where people live, work, visit regularly. Protect accordingly:
- Encryption: TLS for transmission, encryption at rest for storage. See security and operations for our standard approach.
- Access control: Limit who can view location data. Log every access with an audit trail, including which user viewed whose location and when.
- Retention: Automatic deletion after retention period. Delivery tracking data can typically be aggregated after 30 days. Field worker tracks after payroll processing. Don't keep data "just in case".
- Anonymisation: For analytics, reduce coordinate precision (3 decimal places gives ~110m accuracy, sufficient for heat maps) or apply k-anonymity techniques. Aggregate rather than store individual tracks long-term.
Breach risk: A location data breach is particularly sensitive. Historical location data can reveal home addresses, workplace, daily routines, and personal associations. The reputational and legal exposure from a location data breach exceeds that of many other data types.
Common Patterns
Recurring implementation patterns we use across location-aware applications:
Store Locator
The classic "find your nearest" flow. Four steps, each building on the geocoding and spatial query patterns covered above.
User enters postcode or grants location permission. Use address autocomplete or Geolocation API.
Geocode the input (if postcode/address). Cache the result.
Query PostGIS for stores within radius, ordered by distance. ST_DWithin then ST_Distance.
Display results as list and map markers. Cluster if many results. Link to directions.
Delivery Zone Check
Zone-based pricing and availability checks tie directly into order management workflows. The spatial query runs during checkout, but the zone definitions feed scheduling, pricing tiers, and fulfilment routing.
Admin defines delivery zones as polygons in a map editor. Store as PostGIS geometry.
Customer enters delivery address during checkout. Geocode to coordinates.
Query PostGIS: SELECT zone FROM delivery_zones WHERE ST_Contains(boundary, point).
Return zone-specific pricing, delivery windows, or "outside delivery area" message.
Field Worker Dispatch
Dispatch combines spatial queries with service delivery workflows. The location layer finds the nearest available worker; the service delivery system handles assignment, SLA tracking, and completion confirmation.
Workers report location periodically via mobile app. Store in time-series table.
New job arrives. Geocode job address if not already done.
Find available workers within reasonable distance. Factor in current job queue and skills.
Assign job. Send notification with navigation link. Update dispatch board in real-time via real-time dashboard.
Technology Stack
Our standard stack for location-aware applications, deployed on infrastructure sized for the workload:
Database
- PostgreSQL with PostGIS extension
- Geography type for coordinate storage
- GiST indexes on spatial columns
- TimescaleDB for high-volume tracking data
Geocoding
- Google Maps or Mapbox as primary provider
- Postcodes.io for UK postcode lookups
- Results cached in database
- Queued processing for bulk operations
Map Display
- Mapbox GL JS or Maplibre for web
- React Native Maps or Mapbox SDK for mobile
- Vector tiles for custom styling
- Server-side clustering for large datasets
Routing
- Mapbox Directions or OSRM for simple routing
- Google OR-Tools for optimisation
- Commercial APIs for complex constraints
- Cached distance matrices where appropriate
What good location-aware architecture delivers
-
Accurate geocoding Addresses converted to coordinates reliably, with caching to control costs.
-
Fast spatial queries "Find nearest" and "within area" queries that perform at scale using PostGIS.
-
Interactive maps Maps that render smoothly with thousands of points and work offline when needed.
-
Efficient routing Optimised routes that account for real constraints, not just shortest path.
-
Reliable geofencing Entry/exit detection that handles GPS noise and edge cases.
-
Privacy compliance Location data handled with appropriate consent, minimisation, and security.
Location capabilities built on solid foundations: PostGIS for spatial queries, proper geocoding strategies, maps that perform, and privacy handled correctly from the start.
Build Location-Aware Features
Store locators, delivery routing, territory management, asset tracking, field workforce coordination. Location features that perform at scale, cost predictably, and handle the edge cases that naive implementations miss.
Talk through your location requirements →