Skip to content

Find My Friends#

Problem statement (interviewer prompt)

Design Find My Friends: users opt-in to share their live location with chosen people. The watcher sees the latest position on a map with <5s lag, gets geofence alerts ("X arrived at home"), and an emergency-SOS button. Battery-efficient on the device side.

flowchart LR
  A([User A])
  B([User B])
  LOC[Location Service]
  WS[WebSocket Gateway]
  PRES[(Presence KV)]
  A -->|update loc| LOC --> PRES
  B --> WS
  WS --> PRES
  PRES --> WS --> B

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class A,B client;
    class WS edge;
    class LOC service;
    class PRES datastore;
flowchart TB
  subgraph Apps
    A([User A app])
    B([User B app])
  end

  subgraph Edge
    LB
    WS[WebSocket gateway<br/>persistent connection]
  end

  subgraph Loc[Location plane]
    ING([Location Ingest])
    BATCH[Adaptive batching<br/>battery aware]
    GEO[(Presence KV<br/>user_id -> lat lng ts)]
    HIST[(Optional history)]
  end

  subgraph Sharing[Sharing graph]
    REL[Sharing Service]
    ACL[(Permissions)]
    GRP[Groups / families]
    TEMP[Temp share link]
  end

  subgraph Fanout[Notify subscribers]
    PUB[[Pub/Sub per-user channel]]
    SUB[Subscriber sessions]
  end

  subgraph Privacy[Privacy & precision]
    BLUR[Coarsen / blur]
    OFF[Stop sharing]
    AUDIT[Audit log]
  end

  subgraph Notif
    PUSH((APNS / FCM))
    GEOFENCE([Geofence trigger])
    EMERG[SOS / emergency]
  end

  A --> LB --> WS --> ING --> GEO
  GEO --> PUB --> SUB --> WS
  ING --> HIST
  Sharing --- A
  Sharing --- B
  Privacy --- ING
  Privacy --- GEO
  Notif --- GEOFENCE

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class A,B client;
    class WS edge;
    class BATCH,REL,GRP,TEMP,SUB,BLUR,OFF,EMERG service;
    class GEO,HIST,ACL datastore;
    class PUB queue;
    class ING,GEOFENCE compute;
    class PUSH external;
    class AUDIT obs;

Update cadence#

  • High when moving fast / app in foreground; rare when stationary or background.
  • Significant-location-change OS callback to save battery.

Privacy#

  • Sharing is opt-in per friend, with temporary share windows.
  • Coarsen precision for low-trust grants.
  • Server stores last known location only by default; history is per-user opt-in.

Subscriber notification#

  • Each user has a topic; subscribers receive deltas over WS.
  • Geofence triggers: client-side or server-side rules (e.g., "notify me when X gets home").

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD Pub/Sub & message brokers topics, consumer groups, delivery semantics pub-sub-pattern
HLD Observability metrics, logs, traces, SLOs observability
HLD Realtime protocols WS / SSE / polling / gRPC streaming realtime-protocols
LLD Async models futures / async-await / coroutines / actors async-models

Quick reference#

Functional#

  • Share live location with chosen friends/family.
  • See last-known and live position on map.
  • Geofence alerts.
  • Temporary share links.
  • Emergency SOS.

Non-functional#

  • Update latency < 5 s glass-to-glass.
  • Battery-efficient (sparse updates when idle).
  • Strong privacy controls.

Capacity#

  • 100M+ users; 100s of millions of small updates / hr.
  • WS connections sized like chat (~100k per gateway).

Schema#

  • presence(user_id, lat, lng, accuracy, ts) Redis hash with TTL
  • sharing(owner_id, viewer_id, since, until, precision)
  • geofences(user_id, region, trigger_event)

Trade-offs#

  • Always-on WS vs push wakeup: WS for foreground; push notifications wake app briefly.
  • Per-user channel vs presence query: channel push is timelier; periodic query is simpler.
  • Server-side history = nice UX but big storage/privacy risk; default off.

Refs#

  • Apple Find My architecture talks (WWDC), Google Family Link / Maps share location, ByteByteGo "Design proximity / find friends".

FAQ#

How does Find My Friends share live location with low battery drain?#

Clients use significant change location updates and motion based triggers rather than constant GPS polling. Updates are batched and sent only when the user moves meaningfully or a watcher is active.

How does the system push location to watchers within 5 seconds?#

Watcher devices hold a WebSocket to a gateway. When a sharer publishes a new fix to a presence KV store, a fan out service pushes it to each subscribed watcher in real time.

How do geofence alerts work in Find My Friends?#

Each watcher defines named places. The location service runs a point in polygon check against the user's fences on every update and emits an arrived or left event when the boolean flips.

How is location privacy enforced?#

Sharing is explicit and opt in per recipient, with time bounded options like share for one hour. Server side ACLs are enforced on every location read so unsubscribed users see nothing.

How is the emergency SOS button implemented?#

SOS sends a high priority signal over the same gateway plus a fallback push. It surfaces last known location and battery to emergency contacts even if the device goes offline after.