In short
Building a geolocation app means four decisions, none of which are about screens. Match the positioning source to what each feature actually needs instead of defaulting to continuous fine GPS. Design for the permission the user will realistically grant, not the one you want. Separate live positions from movement history from business events in the backend, because they have three different read patterns and three different retention rules. Then engineer privacy as a requirement rather than a policy page. A store finder is a modest build. Live multi-entity tracking is a distributed systems project wearing an app as its interface, and the difference in cost between those two is roughly an order of magnitude.
Location turns a generic app into a contextual one. Delivery tracking, store finders, field team coordination, proximity offers, ride matching, asset recovery: all of them are ordinary software with a coordinate attached, and the coordinate is where the difficulty lives.
The difficulty is rarely where a feature list suggests. Drawing a map is a solved problem with excellent libraries. What is not solved, and what every location project rediscovers, is that raw positions are noisy, that the operating system will not let you have them as freely as your design assumes, that proximity queries which are instant at ten users are fatal at ten thousand, and that movement history is one of the most sensitive datasets a company can accumulate.
This guide walks the stack in the order it will hurt you: positioning, permissions, backend, geofencing, privacy, validation, and then scope. It reflects how we build these systems inside our mobile app development services and in production logistics work.
Key takeaways
- Request the accuracy tier the feature needs. Over-requesting causes battery complaints, review rejections, and permission denials, and buys nothing.
- Design the product to be useful with foreground-only permission. Apps that degrade gracefully get approved faster and denied less.
- Separate the hot path (current position, in memory) from history (append-only tracks) from business events (transactional database). One table for all three fails at scale.
- Use platform geofencing instead of continuous polling wherever the feature allows. The operating system monitors boundaries at near-zero battery cost.
- Apply hysteresis and dwell confirmation to every fence. Without them a device parked on a boundary will flap and spam the user.
- Location traces reveal homes, workplaces and health visits. Decide precision and retention at design time, because both are far cheaper to restrict before launch than after.
- Field-test positioning quality before committing the roadmap. One week of measurement in the actual target environment routinely changes the architecture.
Positioning is a fusion of sources, and picking the wrong one is expensive
A phone does not have a GPS sensor in the way a car navigation unit does. It has a satellite receiver, a cellular radio, a Wi-Fi radio, a Bluetooth radio, and a set of motion sensors, and the platform fuses whichever of them are available into a single estimate with a stated accuracy. You do not choose a sensor. You request a tier of accuracy and a cadence, and the operating system decides how to satisfy it.
That abstraction is genuinely good, and it is also where the first design mistake gets made. Requesting the highest accuracy tier continuously is the path of least resistance, it works flawlessly on the developer's desk, and it is wrong for the large majority of features. A store finder needs one coarse fix. A geofenced reminder needs no continuous tracking at all, because the platform can wake your app on a boundary crossing. Only live tracking of a moving entity genuinely needs a continuous fine stream, and even then not at the maximum rate.
The consequences of over-requesting are not subtle. Battery drain shows up in reviews. Continuous background location triggers the strictest tier of app store review. And on both platforms, the permission dialog for always-on precise location is the one users decline most often, so an app that demands it converts worse than one that asks for less. Requesting honestly is a product decision with a measurable effect on adoption, not a technical detail.
Positioning sources, what they cost, and where they fail
| Source | Typical accuracy | Power cost | Where it fails |
|---|---|---|---|
| Satellite (GNSS) | A few meters outdoors | High | Indoors, tunnels, dense urban canyons, and the first minute of a session |
| Wi-Fi fingerprinting | Tens of meters | Low | Areas with few mapped access points, and rural coverage generally |
| Cellular network | Hundreds of meters | Minimal | Anything needing street-level precision |
| Bluetooth beacons | Room level indoors | Low on the phone | Requires deploying and maintaining physical hardware |
| Motion sensors | Relative, drifts over time | Very low | Absolute position; useful only to carry between real fixes |
Accuracy figures are the commonly cited working ranges for each technology rather than a guaranteed specification; real accuracy depends on the environment, and the environment is exactly what the last column is about.
Which accuracy tier does this feature actually need?
What does the feature do with the position once it has it?
-
It shows the user something near them, once
One coarse fix, foreground only
A store finder, a local weather panel or a regional content switch does not need meter accuracy and does not need a second reading. A single low-accuracy request costs almost nothing and never prompts for background access.
-
It reacts when the user arrives somewhere
Platform geofencing, no continuous tracking
Registering a boundary and letting the operating system wake you is dramatically cheaper than polling, and it keeps the app out of the strictest permission tier because you are not holding a location stream open.
-
It records where the user went
Fine accuracy, adaptive cadence, durable local writes
A recorded track is judged on its shape and its total distance, so accuracy matters, but cadence can relax on straight sections. The critical requirement is writing incrementally to disk, because the process will be terminated at some point.
-
It shows one user where another entity is, live
Fine accuracy plus an ingestion backend and a push channel
This is the expensive branch. It brings continuous background location on the reporting device, a stream ingestion path on the server, a live store, and a push channel to the watching client. It is a different project from the other three.
Work through this once per feature, not once per app. Most products contain features from three of these four branches, and treating them all as the most demanding one is the single most common cause of location battery complaints.
The permission model decides your product, so design for it first
Both major platforms have spent years narrowing what an app may know about a user's location and when. The current shape is broadly consistent across them: the user can grant approximate or precise accuracy, can grant access only while the app is in use, can grant a single one-time permission, and can revoke or downgrade any of it later from settings without telling you. Background access is a separate, harder grant, and on both platforms it is subject to review scrutiny and to periodic re-prompting.
This means the honest planning assumption is that a meaningful share of your users will be running your app with approximate accuracy, foreground only. A design that becomes useless in that state does not have a permission problem, it has a product problem, and no amount of persuasive copy in the prompt fixes it. The apps that do well in this environment are the ones where each permission upgrade unlocks a visibly better experience rather than being the price of entry.
Sequencing matters as much as the design. Requesting location on first launch, before the user has seen anything worth trading for it, produces the highest denial rate of any pattern. Requesting it at the moment the user taps something that obviously needs it, after a short in-app explanation of what you will do with it, produces the lowest. This is not a growth hack, it is the pattern both platforms explicitly recommend and the one their reviewers look for.
Permission flows that work, and the ones that get declined
Do this
- Explain before the system promptA short in-app screen stating exactly what is collected and what the user gets for it, shown immediately before the OS dialog. The user then answers the real prompt already knowing the answer.
- Ask at the moment of useThe request fires when the user taps "find near me" or starts a trip, so the reason is self-evident and the timing feels like a response rather than an interruption.
- Degrade visibly, not silentlyWith approximate accuracy, show a wider radius and say so. The user understands the trade they made and knows how to change it, which is where later upgrades come from.
- Re-check the grant every sessionPermissions can be downgraded in settings at any time. Reading the current state on each launch, rather than caching what the user said in onboarding, prevents a whole class of confusing failures.
Not this
- Requesting everything at first launchA cold always-on precise location prompt before any value has been demonstrated. Highest denial rate of any pattern, and a denial is much harder to reverse than a delayed request.
- Blocking the app on the grantA hard gate that makes the product unusable without background location. Reviewers treat this as coercion, and users who cannot evaluate the app cannot be convinced to trust it.
- Requesting background for a foreground featureAsking for always-on access to power a feature the user only ever triggers while looking at the screen. This is the most common rejection reason in review, and it is entirely self-inflicted.
- Treating approximate as brokenShowing an error state when precise accuracy is unavailable. The user granted something usable and got a wall, which reads as punishment for a reasonable choice.
Every item on the right column is something we have seen cause either a measurable denial spike or a review rejection on a real project. None of them are hypothetical.
The geo backend: three data shapes, not one
Location systems answer two questions, and they are structurally different. "Where is this entity right now" is a key lookup that must be fast and is almost never historical. "What is near this point" is a spatial range query over many entities. A naive implementation puts every position into one table in the primary database and serves both from it, which works beautifully in development and degrades badly in production, because the write volume of a position stream and the read pattern of a proximity search are actively hostile to each other.
The architecture that holds up separates three things. Current positions live in a fast key-addressed store, overwritten rather than accumulated, because yesterday's live position has no value. Movement history is appended in batches to storage designed for sequential writes, downsampled on a schedule, and read rarely. Business events, meaning the things the rest of your system cares about such as a delivery confirmed or a fence entered, go into the transactional database, where they belong, at a volume that is a tiny fraction of the raw stream.
For the proximity query itself, use a real spatial index rather than filtering a coordinate range in application code. A relational database with geospatial support handles this well and is the reliable default. Grid cell systems that reduce a coordinate to a sortable cell identifier work well when the design is sharded or stream-based, because they turn a spatial question into a key prefix question. Both approaches are mature. What does not work is computing distances in a loop over every row, which is the implementation you will find in the first prototype of every location project ever built.
What a location backend has to specify before code is written
Ingestion
- Report cadence
- How often each device reports, and whether that rate is fixed or adapts to movement. This single number sets the write volume of the entire system.
- Batching
- Whether devices send each fix immediately or accumulate and send groups. Batching cuts radio wakeups and server request count, at the cost of live latency.
- Validation
- Rejection of implausible fixes, duplicates, and out-of-order arrivals at the boundary, before anything downstream sees them.
- Offline buffering
- What the device does with fixes recorded while it has no connectivity, and how those are reconciled when it returns.
Storage
- Live position store
- Key-addressed, overwritten in place, sized for the number of concurrently active entities rather than total users.
- History store
- Append-only, written in batches, partitioned by time so old partitions can be downsampled or dropped as whole units.
- Spatial index
- Which proximity queries are supported, at what radius, and with what expected result count. A radius nobody bounded is a full scan waiting to happen.
- Retention schedule
- Full resolution for a stated number of days, downsampled for a stated number of months, aggregates thereafter. Written down before launch.
Delivery to clients
- Push channel
- How a watching client receives updates. Polling a live position endpoint at any useful frequency is more expensive than pushing, on both sides.
- Update rate to the map
- Deliberately decoupled from the report rate. Interpolating between sparse updates looks smoother than rendering every raw fix and costs far less.
- Authorization
- Which users may see which entity's position, evaluated per request. Location is the field where a broken authorization rule becomes a safety incident rather than a data leak.
This is the shape of the section a vendor quote should contain and usually does not. If a proposal for a live tracking product itemizes screens but not these rows, it has not priced the actual system.
Geofencing that behaves, which means hysteresis and dwell time
Geofencing is the highest-leverage location feature available, because the platform does the work. You register a set of circular boundaries and the operating system wakes your app when a device crosses one, using whatever cheap positioning is already happening for other reasons. The battery cost approaches zero, and it requires no continuous stream. Both platforms limit how many fences you may register at once, so products with many locations rotate the registered set based on a coarse position, keeping only the plausibly reachable fences active.
The thing nobody warns you about is boundary noise. A device sitting near the edge of a fence will produce position estimates that wander across it, and a naive implementation will fire enter and exit repeatedly. The user experiences this as being spammed in a parking lot. The fix is standard and has two parts: hysteresis, meaning the exit radius is larger than the entry radius so leaving requires more movement than arriving, and dwell confirmation, meaning the app waits to see the device stay inside before treating the entry as real.
The second thing nobody warns you about is that a fence event is a wakeup, not a guarantee of network. Your app may be woken with no connectivity, in a low power state, with seconds of execution time. Fence handlers therefore have to record the event durably and locally first, then attempt delivery. Handlers that assume they can reach the server synchronously lose events, and a lost arrival event in a logistics product is a customer service call.
Geofence implementation checklist
- Entry and exit radii differThe exit radius is meaningfully larger than the entry radius, so a stationary device on the boundary cannot oscillate between states.
- Dwell time before actingAn entry is confirmed only after the device remains inside for a stated period, which suppresses pass-through triggers from someone driving past.
- Events recorded locally firstThe handler writes the event to local durable storage before attempting any network call, because the wakeup may have no connectivity and very little time.
- Delivery is retried and idempotentQueued events are sent later with a stable identifier, so a retry after an ambiguous failure cannot register the same arrival twice.
- Registered set rotatesWith more locations than the platform fence limit, the active set is refreshed from coarse position, and the refresh itself does not require fine location.
- Behavior defined for a denied grantThe feature has a stated fallback when the user has given foreground-only access, rather than silently never firing.
- Fences are testable without travelSimulated location routes exercise entry, exit, dwell and pass-through cases in automated tests, so a regression does not require a car.
Work down this list before considering a fence feature done. Items three and four are the ones that separate a demo from something that survives a week in a real user's pocket.
Location privacy is engineering, not a policy page
A movement history is not ordinary usage data. Given a few weeks of traces, where somebody sleeps, works, worships, and receives medical treatment are all readable, and so are the identities of the people they spend time with. Regulators treat it accordingly, platforms treat it accordingly, and users have learned to be suspicious of any app that wants more of it than the feature obviously requires.
The engineering response is a small number of techniques that reduce exposure substantially and, usefully, reduce your storage bill at the same time. Process on the device where possible, so that a question like "is the user near this store" is answered locally and only the conclusion travels. Truncate precision to what the feature needs, because a neighborhood-level feature does not need meter-level coordinates. Aggregate server-side traces quickly rather than holding raw fixes indefinitely. And make deletion real, meaning it reaches history stores, analytics copies, backups, and any third party you forwarded data to.
For regulated markets, treat location as adjacent to special category data even where it is not formally classified that way: document the lawful basis, gate analytics use behind explicit consent separate from the functional grant, and rehearse the access and erasure workflows before launch. Rehearsing them afterwards means discovering, under a deadline, which of your systems has no delete path. That discovery is common and it is always expensive.
Privacy techniques, ranked by how much exposure they remove
| Technique | What it removes | Cost to adopt |
|---|---|---|
| On-device evaluation | Raw coordinates never reach your servers, so they cannot leak from them or be subpoenaed from them | Low if designed in, high if retrofitted |
| Precision truncation | Street-level detail for features that only need a neighborhood | Low |
| Short raw retention | The long tail of history that carries almost all of the re-identification risk | Low, mostly a scheduled job |
| Consent split from function | Analytics use of location by users who wanted only the feature | Moderate, touches the consent layer |
| Verified deletion path | Copies in backups, analytics stores and third parties that outlive the primary record | Moderate to high, and worth doing before it is demanded |
The ordering reflects how much data stops existing rather than how much effort each takes. The first row is both the strongest and, on most projects, the cheapest to adopt if it is chosen before the client is built.
Terms that appear in location specifications
- GNSS
- Global navigation satellite system. The general term covering GPS and the equivalent constellations operated by other states, all of which a modern phone receiver uses together.
- Horizontal accuracy
- The radius, reported with every fix, inside which the true position probably lies. It is an estimate from the platform, not a guarantee, and filtering on it is the cheapest quality improvement available.
- Geofence
- A registered boundary that causes the operating system to wake an app when a device crosses it, without the app monitoring position itself.
- Hysteresis
- Deliberately making a state change harder to reverse than to make, here by using a larger exit radius than entry radius, so a device on a boundary cannot flap between states.
- Dwell time
- A required period inside a fence before an entry is treated as real, which distinguishes arriving from driving past.
- Downsampling
- Reducing a stored track to fewer points while preserving its shape, so history remains useful at a fraction of the storage and a fraction of the privacy exposure.
These come up in vendor conversations and in platform documentation, and a buyer who knows them can read a proposal critically instead of taking its word.
Field measurement is a scheduled activity, not a final check
Positioning quality is a property of the environment, and the environment is not in your office. An app that measures perfectly in a suburban car park can be unusable in a downtown core with tall buildings, under dense tree cover, in a multi-storey garage, or in the target city you have never visited. This is not a bug you can find by reading code, and it is not one a simulator reproduces.
The practice that works is to record real traces early, before the filtering and display logic is written, using a build whose only job is to log raw fixes with their reported accuracy. A week of that, in the actual places your users will be, produces a library of recordings that then serve as test fixtures for the rest of the project. Every subsequent change to filtering or cadence can be replayed against them in automated tests, with expected outcomes asserted. Accuracy stops being an impression somebody formed on a walk and becomes a test that fails.
Budget the same discipline for the device spread. Power management behavior differs by manufacturer, sometimes aggressively, and the handsets most likely to terminate a background location process are rarely the flagship on the engineer's desk. Validating across the actual device distribution of your user base is real scheduled work. Teams that leave it out do not save the time, they simply discover it after release, in reviews.
A validation sequence that catches problems while they are still cheap
-
Build a logging-only clientDays, not weeks
A minimal app that requests position and writes every fix with its accuracy, timestamp and source to a file. No filtering, no map, no product. Its entire purpose is to collect evidence.
-
Record the real environmentsThe highest value week
Walk and drive the actual routes, in the actual cities, including the hard cases: dense downtown, indoor, underground, and heavy tree cover. Note what you did so a trace can be interpreted later.
-
Turn recordings into fixturesMakes it repeatable
Convert the logs into replayable test inputs with expected outcomes attached, such as a known route distance or a known arrival time at a fence.
-
Develop the filter against the fixturesFast feedback
Every filtering or cadence change is now evaluated in seconds against dozens of real environments, including the ones nobody would think to walk back to.
-
Run the fixtures in continuous integrationPrevents regression
A change that improves suburban accuracy and quietly ruins downtown accuracy fails the build instead of shipping. This is the step that keeps quality from decaying over a year of feature work.
-
Validate on the real device spreadBefore release, always
Test background survival and power behavior on the manufacturers your users actually carry, not only on the newest hardware. Record which devices were tested so the coverage claim is checkable.
The order is the point. Each step produces an artifact the next one depends on, and doing them in this sequence means an architecture-changing discovery arrives in week two rather than in week twelve.
Scoping version one, and where the money actually goes
The cost of a location product is set by three questions, and screen count is not among them. Does it track continuously or on demand? Continuous brings the ingestion pipeline, the battery engineering, and the background permission review. Does it match proximity across many entities? That brings the spatial backend and its capacity planning. Does it need indoor accuracy? That brings hardware, site surveys, and maintenance of physical infrastructure.
Answering those three honestly separates two products that get discussed as if they were one. A store finder with geofenced offers sits almost entirely on platform primitives and is a modest build. A live multi-entity tracking product, whether that is a courier fleet, a field service team, or a ride matching marketplace, is a distributed systems project with an app attached, and the app is the smaller half. Be clear which one you are commissioning, and insist that any quote itemizes the backend separately, because a proposal that prices screens and treats the tracking infrastructure as an implementation detail is not comparable to one that does not.
Whichever tier you are building, the sequence that works is consistent: measure positioning in the field, design the data model with retention included, build the tracking engine as a service with its own tests, and produce the screens last. Location products built screens-first accumulate all of their risk in the final integration, which is the worst possible place to find it. The same principle about comparing quotes line by line that we set out in our guide to choosing a development partner applies with double force here, because the invisible half of this system is the expensive half.
A delivery plan for a live tracking product
-
Field measurementWeeks 1 to 2
Logging client, recorded traces from the real target environments, fixture library, positioning quality established as a number.
Done when A documented accuracy expectation per environment, and a replayable test suite built from real recordings.
-
Tracking engineWeeks 3 to 6
Session recording, durable local writes, filtering, adaptive cadence, background survival, offline buffering and reconciliation.
Done when An interrupted session resumes intact on the lowest-tier target device, verified by test rather than by demonstration.
-
Backend and deliveryWeeks 5 to 9
Ingestion, live position store, history with a retention schedule, spatial index, push channel, per-entity authorization.
Done when A load test at the projected concurrent entity count with proximity query latency measured and recorded.
-
Product surfaceWeeks 8 to 12
Maps, permission flows with in-app disclosure, degraded states for partial grants, notifications, history views.
Done when The product is demonstrably useful with foreground-only approximate permission, tested as its own scenario.
-
Review and hardeningWeeks 11 to 13
Background permission justification, disclosure copy, device spread testing, deletion and access workflow rehearsal.
Done when Store submission passes with the background justification accepted, and an erasure request completes end to end.
Spans assume a small dedicated team and are indicative rather than a quotation. The exit criteria matter more than the durations: a phase that ends without meeting its criterion has moved risk forward rather than retiring it.
Frequently asked questions
How accurate is phone location, really?
Under open sky a modern receiver is typically accurate to within a few meters, and the platform reports an accuracy estimate with every fix that you should filter on. Accuracy degrades substantially in dense urban areas, under heavy tree cover, indoors, and in the first minute of a session before the receiver settles. The practical answer for planning is that outdoor street-level features are reliable, indoor precision requires additional hardware, and any promise of consistent sub-meter accuracy from a phone alone should be treated with suspicion.
Do we need background location permission?
Far less often than product designs assume. If the feature reacts to arrival, platform geofencing handles it without a continuous stream. If the feature only matters while the user is looking at the screen, foreground access is sufficient. Background access is genuinely required when something must be recorded or reported while the app is not in use, such as a courier position feed or a workout recorded with the phone locked. It is worth removing that requirement if you can, because it is the strictest review tier and the most frequently declined prompt.
What database should we use for proximity queries?
A relational database with mature geospatial support is the reliable default and is more than adequate for the large majority of products. Grid cell systems that reduce a coordinate to a sortable identifier are a good fit when the design is sharded or stream-oriented, because they turn a spatial question into a key prefix question. The choice matters much less than avoiding the alternative that appears in every first prototype, which is computing distance in application code across every candidate row.
How much does a geolocation app cost to build?
The range is wide enough that the question needs splitting. A store finder with geofenced notifications sits on platform primitives and is a modest build. A live multi-entity tracking product with an ingestion pipeline, spatial queries at scale, history retention and background reporting is a substantially larger project, and the backend is usually the larger half of it. Any quote worth comparing itemizes the tracking infrastructure separately from the screens, because that is where the variance between proposals actually lives.
How long should we keep location history?
Shorter than instinct suggests, and decided before launch rather than after. A common and defensible pattern is full resolution traces for a small number of days to support dispute resolution and debugging, downsampled traces for a few months where a product genuinely needs historical routes, and aggregates indefinitely. This reduces both storage cost and risk exposure, and it is dramatically cheaper to implement as a schedule from day one than to retrofit onto years of accumulated raw fixes.
Can we test location features without physically travelling?
Mostly yes, if you invest in fixtures first. Recording real traces once with a logging build, then replaying them through your pipeline in automated tests with expected outcomes asserted, covers filtering, distance calculation, fence entry, dwell and pass-through cases repeatably. Simulated routes in the platform tooling cover the rest of the logic. What you cannot fully simulate is power management behavior across manufacturers, so real device testing remains necessary before release.
Should the client be native or cross platform?
If continuous background location, power discipline and platform health or motion integration are central to the product, native has a real advantage, because those APIs are platform-specific and are where most of the engineering effort goes. If location is one contextual feature inside a broader product, a cross-platform client with a thin native module for the tracking path is often the better trade. Decide it from where the difficulty sits rather than from a general preference.
If your roadmap has a map on it and you want the positioning, permission and backend work scoped before it becomes a surprise, talk to AgileTech, a software engineering partner in Vietnam that builds location products from the field measurement up.