I have an app where you claim territory by walking with GPS. It is the only app in my fleet with real retention: of a mature cohort of 65 people measured from their first walk, 10 (15.4%) were still walking a month later.
But too few people got that far. Here is the funnel, counted per install.
first_open 468
auth_shown 333 <- 135 lost
auth_method_tapped 297
auth_succeeded 193 <- 104 lost
walk_started 164
walk_ended 118
territory_claimed 83What does your app demand before anyone experiences its value?
Six cancels per install
Breaking down auth_failed by reason:
cancelled— 360 events across 59 devices, an average of six per install- Apple
AuthorizationError#1000— 144 across 23 devices, same character - Google
timeout17 ·gave_up_waiting11 ·abandoned_process8 — these are genuine technical failures
Nobody hesitated once and moved on. They opened and dismissed the sheet six times, then left.
The whole platform gap lives in this stretch too.
| Per install | Android | iOS |
|---|---|---|
| first_open | 288 | 180 |
| auth succeeded | 112 (51%) | 81 (71%) |
| walk_started | 77 (27%) | 87 (48%) |
Android is half of iOS. The dominant sign-in method differs, and the timeout-family failures cluster there.
People who reached the walk were fine
72% of those who start a walk finish it. And as above, 15% are still walking a month later.
The product is not the problem. The doorway is.
Then the server surprised me
Deferring login requires drawing the map without an account. If that is not possible, this is a large project.
I queried the row-level security policies.
territories SELECT {anon, authenticated}
users SELECT {anon, authenticated}Already open. The map query function allowed anonymous execution too. Calling it directly with the anonymous key returned polygons, names, colours and country codes with no session at all.
The server needed no changes. The gate existed in exactly one place: a branch in the client's root view.
A fork in the road
There are two ways to let people in without an account.
Anonymous sign-in is smooth, and you can promote it to a real account later.
Local storage handed over at sign-in time is more work.
Which would you take?
I took the second. The auth database here is shared across many apps, and the signup trigger fans a profile row out to every app's schema. Creating anonymous accounts would wreck per-app metrics that are already polluted by exactly that. I chose measurability over smoothness.
What changed
- The root branch sends signed-out users to the map. I also removed the observer that bounced users back to login on sign-out — leaving it rebuilds the wall you just removed.
- An in-progress walk is checkpointed to disk under a fixed sentinel owner.
- Login is requested only at the moment you try to save territory. At that point the function returns without touching the phase, so calling it again after sign-in resumes the exact route already walked.
- Once sign-in resolves, sentinel-owned records are handed to that account.
The order is inverted. You walk, you see the shape you drew, and then it asks who you are.
Self-check
- How many gates does a new user pass before their first taste of value?
- Have you counted drop-off at those gates per install — not per user?
- Are you assuming removing a gate needs server work? Have you actually read the policies?
The honest part
I do not know if it works yet. It went to review today, and the verdict metric is the first_open → walk_started ratio. Baseline is 27% on Android and 48% on iOS; I re-measure in 28 days.
The Android timeout failures are also still there. Fewer people pass through that door now, so the blast radius shrinks — the bug does not.
Count attempts per install in your own auth failure events. Near 1 means people decided. Six means something is holding them.