Designing a Location-Based Social Discovery Platform
This article examines the architectural design of a location-based social discovery application similar to Tinder, where users swipe right to like or left to dislike profiles, and mutual likes create a match enabling conversation (though messaging itself falls outside our scope here).
Core Requirements and Architecture
The platform must support profile creation with biographical info and photo uploads, display nearby user recommendations, handle right/left swipes, notify users of matches, and continue functioning correctly as users relocate. The system needs to work across geographically distributed users with varying density.
The high-level design relies on a fleet of microservices behind a gateway. When a profile is created, a service stores user information in a database and queues the user for geo-sharded indexing, ensuring they appear in nearby users' recommendations. The recommendation service queries this index. Swipes flow through a data stream (such as AWS Kinesis or SQS), where worker processes check a likes cache to detect matches and send notifications via WebSockets.
Profile Creation Flow
Profile creation involves both synchronous and asynchronous operations. Synchronously, user photos upload to a file server (like S3), and user data—including location and preferences—persists to a key-value store such as Amazon DynamoDB. The user is also added to a processing queue. An asynchronous worker consumes the queue and passes the user info to a GeoShardingIndexer, which uses geo-libraries such as Google's S2 to map a user's coordinates to a geo-shard, allowing that user to appear in recommendations for nearby users.
Below is a representative JSON structure for the stored user profile:
{ "userId"(PK) : "AWDGT567RTH", "name" : "Julie", "age" : 25, "gender" : "F", "location": { "latitude" : "12.34", "longitude" : "56.78" }, "media": { "images": [ "https://mybucket.s3.amazonaws.com/myfolder/img1.jpg", "https://mybucket.s3.amazonaws.com/myfolder/img2.jpg" ] }, "recommendationPreferences": { "ageRange": { "min": 21, "max": 31 }, "radius": 50 } }
Generating Recommendations
When a user requests recommendations, message the Recommendation Engine—the system calculates which geo-shards fall within the user's required search radius and queries the corresponding shards to return all active users inside those areas. The engine then applies filters based on preferences (age, distance, and other criteria) and returns the ranked result set.
Geo-Sharded Index Internals
A naive approach—using a single Elasticsearch index with default shards—will not scale to Tinder-like traffic. Instead, we can exploit the fact that Tinder recommendations are inherently regional: serving users in India does not require including candidates from the US. By sharding active users according to geographic coordinates, each shard maintains a manageable size for low-latency queries, keeping the distribution balanced. Balance across an N-shard configuration can be measured using the standard deviation of active user counts; a lower value indicates better distribution.
Implementations can use Google's S2 library, which hierarchically decomposes the Earth's sphere into interlocking cells via a quad-tree structure. Larger cells are used for sparse areas (oceans or sparsely populated regions), while smaller cells cover cities and other dense areas. Each cell maps to its own search index, which is queried at recommendation time based on the user's position and active radius.
The S2 library exposes two primary functions: given a lat/long point, return the containing cell; given a circle, return all cells it covers. This enables both the accurate indexing of users at profile creation and the querying of all relevant shards during the recommendation fetch step.
Handling Swipes and Matches
After a recommendation is surfaced, users interact through right (like) or left (dislike) swipes. These events funnel through a swipe ingester, which routes left swipes to a storage stream (persisting to low-cost options like S3 for later analysis). Right swipes flow into a separate stream consumed by matcher worker threads, which then query a LikesCache.
If a user A swipes right on user B, the matcher checks whether B has already liked A. If so, a match is created immediately and both users are notified via a server push mechanism like WebSockets. If not, an entry for "A → B" is stored in the LikesCache for B's later right swipe to consume.
On one path, a process handles the case where a user relocates by picking up the new location update from a queue, converting it to an index update request that moves the user's entry from their old geo-shard to the appropriate new index.
Match Persistence Layer
Match records (both users liking each other) persist to a key-value store such as Amazon DynamoDB. The primary key is typically a composite using both user IDs, and the value field includes match-specific metadata.
Search Cluster Topology
The Elasticsearch cluster contains multiple master nodes organizing two auto-scaling groups (ASGs), each using one coordinating-node ASG for handling incoming queries and a separate data-node ASG. Each data node hosts a balanced share of primary and replica shards. Since multiple indexes are distributed across these data nodes, requests from coordinating nodes will fan out to data nodes to gather results from all relevant shards. Regional query patterns allow the system to keep indexes geo-isolated cibulk shards across several data nodes active at once.
By geographically partitioning the search index that locates users and preferring co-located data nodes, the cluster remains responsive in all regions with reliable query and update paths.
Use of Machine Learning for Optimization
For any connection-based app, the quality of its recommendation feed most directly determines user retention. Probabilistic ranking of potential matches matters immensely. By approximating the probability that a given or inferred feature set will produce a right swipe, we can reorder the user's recommendation set based on likelihood of a match.
Important ranking features include:
- Demographic indicators: age, gender identity, occupation, profession, and context.
- Historical on-platform behavior: past swipes (both directions), historically active geo-regions, average use time, and behavioral cadence.
- Signals extracted from bios: inferred interests, dislikes, or stated preferences via cleaned text embeddings.
- Derived image features: computable biometric features such as face shape, hairstyle, or other visual attributes.
We can express this as a supervised learning problem, where we predict the probability of a right swipe using a proven approach such as Logistic Regression. The output probability values can directly serve as the score for ranking candidate profiles.
We can also further optimize the interaction pipeline. For instance, if user A has already right-swiped user B, and B later completes the instance, a match could post immediately with zero latency by pre-fetching this state. In effect, Bob can be notified of an instantaneous match whenever his swipe aligns symmetrically — with no time-consuming travel out to the network to check compatibility rules.
Digging Into Tinder's Scaling Choices
Tinder's engineering team has published a series of deep dives into how it scales its recommendation engine and supporting infrastructure. The underlying theme is that a global dating app with millions of daily active users cannot rely on a single, monolithic database or a naive query strategy. Instead, the team has leaned on sharding, specialized search tiers, and careful cache management to keep latency low.
Geosharding for Recommendations
The core challenge for Tinder's "discovery" feed is that recommendations are inherently location-based. A user in New York should not see profiles from Los Angeles, and the query volume for "everyone near me" is enormous. Rather than run an unbounded search across all users, Tinder partitions its user base geographically. This sharding approach means each database node handles a defined set of regions, limiting the blast radius of a hotspot and allowing the team to scale horizontally by adding more shards for dense urban areas.
The architecture moves away from a single search index toward a geo-hashed, tiered structure. When a user requests candidates, the system can query specific shards that correspond to that user's immediate geographic neighbors. This avoids scanning distant regions, drastically cutting CPU and I/O costs. However, geographic sharding introduces a consistency problem: profiles move, and a user who swipes right on someone in one city might later appear in another shard if they travel. Managing the state of shared profiles across shards becomes a critical part of the design, leading to a consistency model that tolerates eventual convergence in some cases but requires strong guarantees during active matching sessions.
Operational Wins and Bottlenecks
On the infrastructure side, Tinder has documented two specific operational remedies. First, they tamed their ElastiCache clusters by enabling auto-discovery. Running a large Redis cluster with static configuration files or manual endpoint lists becomes a maintenance nightmare when nodes are added or removed during scaling events. With auto-discovery, each client can query the cluster's configuration endpoint to discover the current list of nodes, allowing the fleet to react to topology changes without redeployment or restarts.
Second, they extended Elasticsearch with custom plugins to reduce query execution time. The default scoring and retrieval mechanisms often perform heavy computations that are wasteful for simple use cases. By writing plugins that short-circuit certain evaluations or pre-filter results, the team improved performance at the search layer without switching their underlying storage engine. These customizations represent a pragmatic choice: when the vendor solution is close to 90 percent of what you need, a surgical plugin can be less disruptive than a full database migration.
Further Reading and Talks
For engineers looking to follow the exact path Tinder took, the team has published a three-part series on geo-sharded recommendations covering the sharding approach, the system architecture, and the consistency guarantees. There are also dedicated write-ups on the ElastiCache auto-discovery work and the Elasticsearch plugin performance improvements. Several engineering talks from Tinder's team are available on YouTube, offering more color on how these systems behave under production load.
References:
medium.com/tinder-engineeringgeosharded recommendations (parts 1, 2, 3)medium.com/tinder-engineeringtaming elasticache with auto-discoverymedium.com/tinder-engineeringelasticsearch plugins for performance (parts 1 and 2)- YouTube: Tinder engineering talks on scaling and architecture
Dive deeper with the original engineering posts and video presentations from the Tinder tech team.













