Tinder is a popular dating app where people create profiles with photos, a short bio, and basic personal details. Users swipe right if they are interested in someone and swipe left if they are not; when two people both swipe right, they “match” and can start chatting. It is commonly used for dating, casual conversations, and meeting new people nearby.
Product Design Requirements
Functional Requirements
- Users should be able to create a profile with photos, interests, and matching preferences.
- Users should be able to set filters such as age range and maximum distance.
- Users should be able to view nearby potential matches that fit their preferences.
- Users should be able to swipe right or left on profiles one at a time.
- Users should be able to receive a notification when there is a mutual match.
Non-Functional Requirements
- The system should provide strong consistency for mutual matches, so a match is created immediately when two users both swipe right on each other.
- The system should support high scale, around 20M DAU and roughly 2B swipes per day assuming 100 swipes per user.
- The system should load each user’s potential match stack with low latency, ideally under 200ms.
- The system should avoid duplicate recommendations by filtering out profiles the user has already swiped on.
Design Setup
Data Model
- User: Represents a person using the app, as well as a profile that can be recommended to other users.
- Swipe: Represents a user’s decision on another profile, either right/yes or left/no. It links a
swiping_userto atarget_user. - Match: Represents a mutual connection between two users after both users swipe right on each other.
API Design
Firstly, we need a POST endpoint to create profile
POST /profile { "age_min": 25, "age_max": 35, "distance": 10, "interested_in": "female" ... }
Secondly, users should be able to fetch a stack of nearby profiles to swipe on.
GET /feed?lat={lat}&long={long}&distance={distance} [ { "user_id": "user_123", "name": "Alice", "age": 25, "bio": "..." } ]
The client passes the current latitude, longitude, and distance because the user’s location can change frequently. Other filters, such as age range and interested gender, do not need to be passed in the request because they are already stored in the user’s profile settings and can be loaded server-side.
Pagination is not strictly necessary here because this is a recommendation feed, not a traditional list. When the current stack is exhausted, the client can request another batch of recommendations.
Lastly, users should be able to swipe yes or no on another profile.
POST /swipe/{target_user_id} { "decision": "yes" }
The target_user_id identifies the profile being swiped on. The authenticated user should be inferred from the request headers, not from the request body.
All endpoints should require authentication. The current user should be identified through a session token or JWT in the request headers. This avoids trusting client-provided user IDs in the request body, which could be manipulated. For example, the swipe API should infer the
swiping_user_idfrom the authenticated session and only accept the target_user_id as the path parameter.