My Solution for Design a Fitness Tracking App with Score: 8/10
by marcci
System requirements
Functional:
- Track Activities
- Set goal
- Monitor progress
Non-Functional:
- Performance: Quick response
- Support peak times such as: holiday...
- Availability: 99.9%
Capacity estimation
Target user for the first year: 100.000
DAUs: 20.000
Request / user: 10 request/day
Request / day: 200.000
Response time: 200-300ms
API design
Add activity:
- user_id: uuid
- type_of_activity_id: number
- startTime: DateTime
- endTime: DateTime
- distance: number (m)
View activily list / view detail:
- query params: fromDate, toDate (yyyyMMdd)
- request params: user_id
- activity_id: for view detail
- response: all saved information
- workload: number
- duration: number (minute)
- calories: number
Add goal:
- user_id
- period: week, day, month
- type: km, times, minutes
- goalValue: number
Monitor progress:
- request params: user_id, goal_id
- response:
- goal: goal_id, period, type, goalValue
- currentValue: number
- status: string (New, On track, success, due)
Database design
Use relational database
User
- id: uuid
- fullName
- phone
- geolocation
- timezone
- lang
- gender
- dob
Workout
- id
- userId: pgk
- value: number
- duration
- startTime
- endTime
- typeOfWorkoutId: fgk
- calories
Type of Workout
- id: number
- name: string
- createdAt
Goal
- goalId: uuid
- userId: uuid: pgk
- startDate
- endDate
- goalValue: number
High-level design
- Rate Limiter: avoid spam
- Load balancer: for multiple location servers
- API Gateway: for API endpoint
- Goal Service
- User Service
- Workout Service
- Redis Cache: to cache user and goal
- Message Queue: for asynchronous communication
- Postgre DB
Request flows
Detailed component design
- For our load balancing strategy, we use index based Layer 4 load balancing so that users are routed to the nearest server to reduce latency
- API Gateway does rate limiting and lets the user know when they are being rate limit gracefully
- We use log based message queues since we do not want to lose user data
- We cache a user's goals and his last N workouts, where N is a configurable parameter. We invalidate the workouts whenever we record a new workout for the user. We invalidate the goals of a user from the cache when the user adds a new goal. For other cases, we use Least Recently Used as our cache eviction strategy
Trade offs/Tech choices
- Postgre for DB
- Redis as caching service
- Kafka for message queue
Failure scenarios/bottlenecks
- User doing workout offline --> can not track distance and geolocation correctly
- during peak hours such as holiday, workout services maybe overload
Future improvements
- Users should be track how far along their goal they have progressed
- Letting the user know when they have hit a goal