| title | README |
|---|
A Hevy-inspired fitness tracking application built with MongoDB + Redis, developed as a final group project for ENCE614016 — Database System and Laboratory.
| Name | Student ID | Role |
|---|---|---|
| Nadira Fayyaza Aisy | 2406368933 | Backend & MongoDB Lead |
| Naufal Rafif Adigama | 2406368965 | Redis & Benchmarking Lead |
| Syifa Sarah Nuraini | 2406368883 | Frontend & Documentation Lead |
Course: ENCE614016 - Database System and Laboratory
Deadline: 15 May 2026
FitSync is a fitness tracker app inspired by Hevy. Users can log workouts, track exercise history, view weekly stats, and compete on a streak-based leaderboard. All powered by a dual-database backend.
| Database | Role in FitSync | Why |
|---|---|---|
| MongoDB | Persistent storage users, workouts, exercises | Document model fits nested workout/exercise data naturally |
| Redis | Real-time leaderboard, session tokens, API cache | Sub-millisecond reads for live rankings; TTL for sessions |
These are not redundant — MongoDB is the source of truth, Redis handles everything time-sensitive and high-frequency.
fitsync/
├── docker-compose.yml # Spins up API + MongoDB + Redis
├── Dockerfile
├── package.json
├── README.md
├── src/
│ ├── index.js # Express entry point
│ ├── models/
│ │ ├── User.js # MongoDB user schema
│ │ └── Workout.js # MongoDB workout schema (nested exercises)
│ ├── routes/
│ │ ├── auth.js # Register, Login → Redis SETEX session
│ │ ├── workouts.js # Log workout → MongoDB + Redis ZADD
│ │ ├── leaderboard.js # Read top 10 from Redis ZRANGE
│ │ └── stats.js # Weekly stats (cache-aside pattern)
│ └── middleware/
│ └── auth.js # JWT + Redis session validation
├── scripts/
│ └── seed.js # Populates MongoDB + Redis with sample data
├── benchmarks/
│ ├── benchmark.js # Latency comparison: Redis cache vs MongoDB
│ ├── results.csv # Raw benchmark output
│ └── benchmark_plot.png # Bar chart of results
└── docs/
├── data_models.md # MongoDB schemas + Redis key design
├── architecture.png # Architecture diagram
└── design_decisions.md # Why we chose each DB for each role
- Docker Desktop installed and running
git clone https://github.com/<your-username>/fitsync-namo.git
cd fitsync-namodocker compose up --buildThis starts three containers: fitsync_api (port 3000), fitsync_mongo (port 27017), fitsync_redis (port 6379).
docker exec fitsync_api node scripts/seed.jsThis creates 3 users (nadira, naufal, syifa), 15 workouts, and seeds the Redis leaderboard.
GET http://localhost:3000/
GET http://localhost:3000/api/leaderboard
POST http://localhost:3000/api/auth/login
POST http://localhost:3000/api/workouts
GET http://localhost:3000/api/stats/weekly/:userId
| Method | Endpoint | Body | Description |
|---|---|---|---|
| POST | /api/auth/register |
{ username, email, password, profile } |
Register new user → saved to MongoDB |
| POST | /api/auth/login |
{ email, password } |
Login → session token stored in Redis SETEX |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/workouts |
✅ | Log workout → MongoDB + updates Redis leaderboard |
| GET | /api/workouts |
✅ | Get all workouts for current user from MongoDB |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /api/leaderboard |
❌ | Top 10 streak rankings → read directly from Redis |
| GET | /api/stats/weekly/:userId |
✅ | Weekly stats → Redis cache first, MongoDB on miss |
{
"_id": "ObjectId",
"username": "nadira",
"email": "nadira@fitsync.com",
"password_hash": "...",
"created_at": "2026-04-26T00:00:00Z",
"profile": {
"age": 21,
"weight_kg": 55,
"height_cm": 162
}
}{
"_id": "ObjectId",
"user_id": "ObjectId",
"date": "2026-05-05T10:00:00Z",
"duration_min": 45,
"calories_burned": 320,
"exercises": [
{ "name": "Squats", "sets": 4, "reps": 12, "weight_kg": 40 },
{ "name": "Deadlift", "sets": 3, "reps": 8, "weight_kg": 80 }
]
}| Key Pattern | Type | Command | TTL |
|---|---|---|---|
leaderboard |
Sorted Set | ZADD leaderboard <streak> <userId> |
No expiry |
session:<token> |
String | SETEX |
3600s (1 hr) |
cache:weekly:<userId> |
String/JSON | SETEX |
300s (5 min) |
Benchmarks compare Redis cache read vs MongoDB aggregation query for the weekly stats endpoint.
Results saved in /benchmarks/results.csv. See /benchmarks/benchmark_plot.png for the chart.
To run benchmarks yourself:
docker exec fitsync_api node benchmarks/benchmark.js

