What is Bump

Bump is battery efficient location sharing + Chatting Mobile App.
Location Sharing
  A group of friends installs bump on their phones and all can track each other's location, speed, battery.
  There can be ghost mode, where you donot share your location with your friends.
  If you ask from Bump, How can i get to friend location it will provide location points to reach there(via 3rd party apps like google map etc)
  Bump can also store location history, list of places you visited earlier
  Phone1 can see location of Phone2 on bump. Helpful if someone is travelling alone in new area
Chat
  send messages, stickers, images, videos, 1:1 or group chats

Why someone chooses Bump over Google map

Social Graph
You can draw of graph of your friends

            🧑 Sarah
                ↓
        ┌─────────────┐
        │             │
🧑Mike │    📍 You   │  🧑 John
        │             │
        └─────────────┘
                ↑
            🧑 Alex

Requirements

Functional
1. Friends can share their current locations with selected friends
2. Friend can see their friends' current locations and obtain directions to a friend's current location
Non Functional
1. Low latency: Location changes should reach authorized friends within a few seconds under normal conditions.
2. Battery efficiency: System should support frequent location updates without excessively draining

BOE

Let, Total Bump App installs: 10M
DAU(Daily active users): 20% = 2M
Every phone sends location update every: 10 seconds
Ingestion: Incoming packets: 2M/10 = 200K requests/sec
Fanout: 1 user has 50 friends, but 10 are online. Location updates are sent to online friends only. Fanout = ~200K x 10 = ~2M messages/sec
Storage: Let every incoming request=200 bytes. 200K requests/sec. 200K x 200 = 40 MB/sec storage. 40Mx86400 = 3.5 PB/day

HLD

flowchart LR

    A["User A Phone"]
    GLB["Global 
Regional LB"] subgraph K8S["AWS Managed Kubernetes Cluster"] direction LR ING["Kubernetes
Ingress"] subgraph INGEST["Ingestion Tier"] direction TB I3["Location Pod N"] I1["Location Pod 1"] I3 ~~~ I1 end RP[("Redpanda Cluster")] subgraph PROC[" "] direction TB subgraph CROW[" "] direction LR subgraph CONSUMERS["Consumer / Processing Tier"] direction TB C3["Location Consumer N"] C1["Location Consumer 1"] C3 ~~~ C1 end CUR[("Current Location
ScyllaDB")] end subgraph FROW[" "] direction LR subgraph FANOUT["Fanout Tier"] direction TB F3["Fanout Pod N"] F2["Fanout Pod 2"] F3 ~~~ F2 end FRIEND[("Friendship / Privacy
ScyllaDB / PostgreSQL")] end end subgraph WS["WebSocket Gateway Tier"] direction TB W3["WS Pod N"] W1["WS Pod 1"] W3 ~~~ W1 end REDIS[("Redis
Connection Registry")] end B["User B Phone"] %% LOCATION INGESTION A -->|"Location update"| GLB GLB --> ING ING --> INGEST INGEST --> RP %% LOCATION STORAGE RP --> CONSUMERS CONSUMERS --> CUR %% FANOUT RP --> FANOUT FANOUT --> FRIEND FANOUT --> WS %% B OPENS WEBSOCKET (via LB; B stays a sink on the right) %% CONNECTION REGISTRY WS --> REDIS %% SERVER SIDE DELIVERY WS -->|"LocationUpdate(A)"| B style PROC fill:none,stroke:none style CROW fill:none,stroke:none style FROW fill:none,stroke:none

User A registers, installs app on his phone

sequenceDiagram
autonumber

    actor A as User A Phone
    participant GLB@{ "type" : "boundary" } as Global LB
Regional LB box AMO AWS/Datacenter participant API@{ "type" : "entity" } as API Gateway participant K8LB@{ "type" : "entity" } as K8s LB participant AUTH@{ "type" : "collections" } as Auth/User Svc
MULTIPOD participant DB@{ "type" : "database" } as User DB participant DEVICE@{ "type" : "database" } as Device Store end participant IDP@{ "type" : "collections" } as IDP A->>GLB: HTTPS POST Register(email/phone, name) GLB->>API: HTTPS API->>K8LB: HTTP K8LB->>AUTH: Create user AUTH->>IDP: Authenticate user IDP->>A: Enter user/pass A->>IDP: User/pass Note over IDP: User/pass valid IDP-->>A: JWT Token Note over A: Store JWT in
Mobile Secure store IDP-->>AUTH: JWT Token AUTH->>DB: Insert user_id + profile DB-->>AUTH: User created A->>API: Register device
JWT Token Note over API: Validate JWT Token API->>AUTH: Store device AUTH->>DEVICE: Insert device_id DEVICE-->>AUTH: Stored AUTH-->>API: Registration successful API-->>A: user_id + auth token

Tables created


// User Identity data
User
----
user_id
name
profile_photo
created_at
privacy_settings
    
Device
------
device_id
user_id
push_token
platform
app_version
last_seen
Location Privacy Permissions table
owner_user_id | viewer_user_id | can_view | updated_at
      A       | B              | true     | ...
      B       | A              | false    | ...

SQL: Create index (owner_user_id, viewer_user_id)
User A can view user B

noSQL(ScyllaDB): Partitionkey=(owner_user_id, viewer_user_id)
SQL database indexing
ScyllaDB
A adds B as friend (friendship ≠ location permission)
A sends a friend request. We need to store the relationship
Friendships table
----------
user_id |friend_id| status  |created_at | updated_at
   A    | B       | ACCEPTED|           |

User A send location to Friend B

WebSocket Service
  What is Web Socket
  Websocket Service(pod-1) will open a connection with Mobile-B once Mobile-B comes online
  Websocket service(pod-1) will create a connection information for Mobile-B(eg: conn-B={TCP IP, port})
  Websocket service(pod-1) will update connection information to Redis, Since this connection information is emphemeral and can change. if B dissconnects and comes back online again, Mobile-B might connect to pod-2
API Gateway
Kubernetes Ingress, Pod Scaling: HPA

Ingestion Tier(Location Service) Tasks:

Perform Authentication.
Extract user from Bearer Token / JWT Token
Validate Header,payload authorization sent from A
latitude ∈ [-90, 90]
longitude ∈ [-180, 180]
timestamp isn't wildly invalid
payload size is reasonable
Normalize & publish to Redpanda.
Create Internal Event
Topic: location-updates
Partition X
{
    event_id: "evt-98765",
    event_type: "LocationUpdated",
    user_id: "A123",
    lat: 18.5204,
    lon: 73.8567,
    accuracy_m: 8,
    speed_mps: 4.2,
    timestamp: ...
}

Redpanda
Redpanda over kafka: Due to predictable latencies
Partition key = userId. So that all location events for user=A go to the same partition
Partitions, Consumer Groups, Brokers

Consumer Tier:
Consumer reads Topic=location-update & writes to ScyllaDB

user_id       A123
latitude      18.5204
longitude     73.8567
accuracy      8
speed         4.2
timestamp     10:05:30

ScyllaDB(NoSQL DB)
  Why ScyllaDB: millions of requests/sec — where eventual consistency is acceptable
  Over SQL: Because noSQL(implemented using LSM Tree) can scale horizontally while SQL(implemented using BTree) cannot
  Over Cassandra: Seastar Framework is fast wrt Java JVM

Fanout service(Who is allowed to receive A's location?) to Websocket Service
1. Fanout Recieve same Kafka Topic(location-updates) and gets A's friends, preferences from Friendship DB(Location Privacy Permissions table, Friendships table)

Kafka Message
user_id       A123
latitude      18.5204
longitude     73.8567
accuracy      8
speed         4.2
timestamp     10:05:30

2. Fanout svc queries Redis for conn-id of Mobile-B, ie to which pod Mobile-B is connected?

{
  "gateway": "pod-1",
  "connection_id": "conn-b"
}

3. Fanout svc sends {conn-id, userA-lat,lon,timestamp} to websocket svc. This message can be sent over KAFKA(another topic) or gRPC or A custom lightweight protocol or Internal messaging

{
  "connection_id": "conn-b",
  "event": "LOCATION_UPDATED",
  "user_id": "A",
  "latitude": 18.5204,
  "longitude": 73.8567,
  "timestamp": "2026-09-08T06:05:30.123Z"
}

4. Websocket svc recieves msg and find B's location using conn-id and Pushes data immediately since websocket is already opened

sequenceDiagram
    actor A as User A Phone
    participant GLB@{ "type" : "entity"} as Global
Regional GLB box AWS AMO Datacenter participant API@{ "type" : "entity"} as API Gateway participant KLB@{ "type" : "entity" } as kubernets
Ingress participant LOC@{ "type" : "collections" } as Ingestion Tier

Location
Svc
MULTIPOD participant Consumer@{"type": "collections"} as Consumer Tier

MULTIPOD participant FAN@{"type": "collections"} as Fanout
Svc
MULTIPOD participant K@{"type": "queue"} as Kafka / Redpanda participant CUR@{"type": "database"} as Current Location
ScyllaDB participant FRIEND@{"type": "database"} as Friendship /
Privacy DB participant Redis@{"type": "database"} as Redis participant WS@{"type": "collections"} as WebSocket
Svc

POD-1 end actor B as User B Phone Note over A: A and B are
already friends
A has allowed
B to see A's location B->>WS: Open WebSocket connection
GET /ws
Host: amo.com
Authorization:Bearer WS-->>B: Connection established
HTTP 200 OK Note over WS: conn_id:"conn-b",
Store in Redis User-B
connected to me WS->>Redis: Key:userB, value:POD-1 Note over A: Send attributes A ->> GLB:POST /v1/location
Host:amo
Authorization: Bearer
{lat=1,
lon=2,
timestamp,
speed=2m/s} GLB->>API: HTTPS{location} API->>KLB: HTTPS POST /v1/location Note over KLB:Mapping /v1/location
to Location Svc KLB->>LOC: location Note over LOC: Authenticate using Bearer Token
Derive username from Bearer Token LOC ->> LOC: Validate location, size, timestamp
Publish Location K->>K: Partition key=user_id LOC->>K: Topic=location-update
{
event_id: "evt-98765",
event_type: "LocationUpdated",
user_id: "A",
lat: 18.5204,
lon: 73.8567,
accuracy_m: 8,
speed_mps: 4.2,
timestamp: ...
} K->>Consumer: Topic=location-update Consumer->>CUR: INSERT INTO table
user_id A123,latitude:18.5204,longitude:73.8567
accuracy:8,speed:4.2,timestamp:10:05:30 K->>FAN: Topic=location-update (same msg as above) FAN->>FAN: Find friends of A who are eligible to be updated FAN->>FRIEND: SELECT friend_id
FROM location_visibility WHERE user_id = 'A123' AND can_view_location = true; FRIEND-->>FAN: B FAN->>Redis: GET connection:B Redis-->FAN:{
"pod": "1",
"connection_id": "conn-b"
} FAN->>WS: A's location is updated
{
"connection_id": "conn-b",
"event": "LOCATION_UPDATED",
"user_id": "A",
"latitude": 18.5204,
"longitude": 73.8567,
"timestamp": ""
}
Over KAFKA(another topic) or gRPC or A custom lightweight protocol or Internal messaging WS->>WS: Find websocket for conn-b WS->>B: {
"event": "LOCATION_UPDATED",
"user_id": "A",
"latitude": 18.5204,
"longitude": 73.8567,
"timestamp": ""
} Note over B: Update A's marker on map

Scenarios

B is Offline, later comes online

Mobile-B breaks websocket connection and Web-Socket module updates same in Redis
fanout service quries Redis and no information is recieved
Later B comes online, Mobile-B sends "ping" to WebSocket service(pod-2). Ping means send all updates for me
Websocket service(pod-2) upddates conn-id in Redis and sends a Kafka message.
This message is recieved by Fanout service and finds latest updates of Mobile-B's friends from ScyllaDB(since friends have moved a lot by then).

API Design (CRUD)

REST API?
REST API Versioning(v1,v2)

1. User can create Account on Bump

2. Read location of friend on bump app

3. Update self profile to include friends(whom you will follow)

4. Delete friend

5. Delete Account


curl -X POST -H "Content-Type: application/json" 
-d '{"name": "user_id", "long", "lat"}' 
http://127.0.0.1:8080/v1/create_account -vvv
          

// data sent as query parameter
// instead of sending as json data
curl -X GET http://127.0.0.1:8080/v1/get_location?friend_id=friend_id
        

curl -X PUT -H "Content-Type: application/json" -d 
'{
  "user_id": "current_user_id", 
  "friends_to_follow": ["new_friend_id"]
}' 
http://127.0.0.1:8080/v1/update -vvv
        

curl -X DELETE -H "Content-Type: application/json" 
http://127.0.0.1:8080/v1/delete_friend
-d '{
  "user_id": "id1",
  "friend_id": "friend_to_delete"
}' 
        

curl -X DELETE -H "Content-Type: application/json" 
http://127.0.0.1:8080/v1/delete_account
-d '{
  "user_id": "id1",
}'
        

// Create account
//url=bump.amo.com
POST https://url/v1/create_account 
header {
  Authorization: {Bearer "API_KEY_TOKEN"},

  /*Mandatory added by HTTP Start*/
  Content-len: 0                        
  Host:        //Calculated when req is sent
  UserAgent: Postman
  Accept: */*       
  Accept-Encoding: gzip, deflate, br
  Connection: Keepalive
  /*Mandatory added by HTTP End*/
}
body {  //JSON
  "user_name": "",
  "lattitude": "",
  "longitude": ""
}
        

//Read Location of friends
GET https://url/v1/get_location
header {
  Authorization: {Bearer "API_KEY_TOKEN"},
  ..other fields..
}
body {  //JSON
  "my_username": "", 
  "friend_name": "",
}
          

// Add new friends to look
PUT http://url/v1/update
header {
  Authorization: {Bearer "API_KEY_TOKEN"},
  ..other fields..
}
body {  //JSON
  "my_username": "", 
  "friend_name": "",
}
        

// Add new friends to look
PUT http://url/v1/delete_friend
header {
  Authorization: {Bearer "API_KEY_TOKEN"},
  ..other fields..
}
body {  //JSON
  "my_username": "",
  "friend_id": ""
}
        

// Add new friends to look
PUT http://url/v1/delete_account
header {
  Authorization: {Bearer "API_KEY_TOKEN"},
  ..other fields..
}
body {  //JSON
  "my_username": ""
}