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
|
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
|
|
SQL database indexingScyllaDB |
A adds B as friend (friendship ≠ location permission) A sends a friend request. We need to store the relationship
|
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
|
Normalize & publish to Redpanda. Create Internal Event
|
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
|
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 |
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|