Skip to main content

System Design Questions

Design Tinder — System Design Interview Guide

Design Tinder is a system-design interview that asks you to build a location-based dating app: users swipe through profiles, mutual likes become matches, matched users chat. The hard part is the swipe-deck recommendation engine and geospatial filtering at low latency.

By Alex Chen, Founder, InterviewChamp.AI · Last verified

Reported in interviews at

  • Meta
  • Bumble
  • Match Group
  • Snapchat
  • Uber

Sourced from Glassdoor, Levels.fyi, and Blind interview reports.

Functional requirements

  • Create a profile with photos, age, location, and preferences
  • Receive a deck of candidate profiles filtered by location and preferences
  • Swipe right (like) or left (pass) on a profile
  • Detect mutual likes and create a match
  • Send messages within matched conversations

Non-functional requirements

  • Deck-load latency: <1 second for the next batch of profiles (p95)
  • Swipe write QPS: peak ~30K/sec globally
  • Match notification: <2 seconds from second swipe to both users notified
  • Scale: 75M active users, 1.6B swipes/day, ~30M matches/day

Capacity estimation

Public 2023 scale: ~75M monthly active users, ~10M daily active users, ~1.6B swipes/day. That's 1.6B / 86,400 × 3 (peak factor) ≈ 55K swipe writes/sec at peak. Each swipe is a tiny row (~50 bytes: swiper_id, target_id, direction, timestamp), so daily write storage is 1.6B × 50 = 80 GB/day = ~30 TB/year before replication.

Deck reads: 10M DAU × ~100 cards swiped/day / 86,400 × 3 ≈ 35K deck-card serves/sec. Each deck fetch requires geospatial + preference + 'haven't swiped yet' filtering, which is the dominant read cost. Profile photos are stored in object storage; average 4 photos × ~200 KB compressed = 800 KB/user → 75M users × 800 KB = ~60 TB. Match storage: ~30M matches/day × 200 bytes metadata = ~6 GB/day. Messages are smaller than dating volumes might suggest because only matched pairs chat; typical chat-message throughput is <10K/sec global.

High-level design

Three logical services drive the product. The user service stores profiles, photos (refs to object storage), and preferences. The discovery service generates each user's swipe deck. The match service handles swipes, detects mutual likes, and creates matches. A messaging service (architecturally similar to Design WhatsApp) handles post-match chat.

The discovery service is the heart. A precomputation pipeline runs continuously: for each active user, generate a ranked candidate list of ~500 profiles matching their basic filters (age range, distance from current location, gender preferences). The candidate set lives in a per-user cache (sharded by user_id), refreshed every hour or on significant location change. When the user opens the app and the client requests the next 10 cards, the discovery service pops them from the cached candidate list, applies last-mile filters (cards the user has already swiped in this session, recently rejected with cooldown), and returns them. Geospatial filtering uses a geohash grid (same pattern as Design Uber) — find users within ~50 km of the requesting user, then apply preference filters.

The match service handles swipes. Each swipe writes a row to a sharded relational store (sharded by swiper_id). When a 'like' is received, the service checks whether the target has previously liked the swiper — a single point read against the same store by (target_id, swiper_id). If yes, it's a mutual like: write a match row, notify both users via the messaging service's persistent connection. Photos and other large user data live in object storage behind a CDN.

Deep dive — the hard problem

The deep dive is the candidate-ranking and mutual-like detection problem. Naïve mutual-like detection requires reading every prior swipe to check if the target previously liked the swiper, which is impossibly hot for popular users — a top-percentile profile might have 10K incoming likes/day. The standard answer: shard the swipes table by swiper_id (write side) AND maintain an 'incoming likes' index keyed by target_id. On a like, write to both indexes (one strong, one async-replicated). Mutual-like detection becomes: 'do I have an entry in (target=me, source=them)?' — a single keyed read on the incoming-likes index. The async lag between primary and inverted index means a small window where mutual detection is slow; cap the window at a few seconds with a synchronous fallback for the rare race.

Second deep dive: candidate ranking. The popular-target problem is also a fairness problem — without intervention, 80% of swipes go to 20% of users and most users see no matches. Production systems implement an exposure-balancing layer in the candidate pipeline: track per-user 'shown count' over a rolling window; cap the rate at which a profile can be served to others. This is bonus signal: mention that the discovery system is partly an optimization problem (maximize matches) and partly a fairness problem (don't winner-take-all), and that ranking signals include profile-completeness, recency-of-activity, and prior swipe behavior.

Third: deck staleness. A user who swipes 100 cards in a session exhausts their precomputed batch; the system needs to refresh on the fly. Pattern: trigger an async refresh when the user is 80% through the current batch; if they outpace the refresh, fall back to a cheaper online query (geohash + recent-activity filter) for the next batch. Mentioning this signals you've thought about session dynamics, not just steady state.

Common mistakes

  • Joining the swipes table with the users table on every mutual-like check — fails at 1B-swipe scale
  • Precomputing the candidate deck once and never refreshing — heavy swipers exhaust it in minutes
  • Forgetting the inverse-index for incoming likes — pushes mutual-like detection to O(N) reads
  • Ignoring the popularity-fairness problem; interviewer will ask 'why does my friend never get matches'
  • Designing matching as synchronous DB joins instead of a precompute + low-latency cache pattern

Likely follow-up questions

  • How would you handle a malicious user creating 10K fake profiles?
  • What changes if you add a 'super-like' feature with limited daily quota?
  • How would you implement passport mode (swipe in any city)?
  • How would you detect catfishing (photos stolen from elsewhere)?
  • How would you support a paid-tier 'see who liked you' feature without scaling the read load 100×?

Practice Design Tinder live with an AI interviewer

Free, no sign-up required. Get real-time feedback on your design.

Practice these live

Frequently asked questions

How long is the Design Tinder system-design interview?
45–60 minutes. Tinder's own loop runs 60 minutes and focuses on the recommendation deck and matching algorithm. Match Group brands (Tinder, Hinge, OKCupid) share most of this question.
Do I need to know the actual matching algorithm Tinder uses?
No — Tinder's actual algorithm is proprietary and changes. Interviewers expect you to design a generic candidate-rank + filter pipeline and discuss tradeoffs (popularity-fairness, recency, completeness). Inventing a specific score function is bonus signal.
Should I cover messaging in detail for Design Tinder?
Briefly. Note that post-match messaging is architecturally a smaller version of Design WhatsApp (persistent connections, offline queue, encryption). Spending 10 minutes on chat costs time you need for the discovery pipeline, which is the unique part of Tinder.
What's the most common reason candidates fail Design Tinder?
Missing the inverse-index pattern for mutual-like detection. Falling back to 'I'll just query the swipes table' shows the candidate hasn't thought about read patterns at scale. Source: Match Group interviewer feedback shared on Blind 2023.