Match Modeling for a Tinder-Like Dating App

Jeff Jenkins
5 min readJan 13, 2021

How do you move from requests to matches? A pseudo-coded guide.

Photo by William Iven on Unsplash

I’ve been working on a dating app recently that is meant to mimic tinder’s functionality with one caveat being that the intended audience for this app is vegetarian. I’m most experienced with Rails, so I’ve used that for my backend MVC. I love working with React and React Native, so naturally the frontend for this mobile application is React Native. Like any good project that’s worth its weight in code, I have paid particular attention to the backend domain modeling. What has particularly tripped me up, or at least given me a prolonged feeling of consternation, has been how exactly to design the architecture around a match request. Do you design a request model that has boolean attribute (lets call it ‘confirmed’) that once its value turns to true triggers the creation of a match instance that has two user id foreign keys? I’ve thought about this quite a bit, sitting in my chair, staring at the wood grain on my desk. That model felt wrong. It seemed bloated and clunky, which are two things that at a foundational level can lead to unnecessary and confusing patchwork later.

There has to be a better way. So like any (novice, in my case) software engineer, I scoured the internet for answers with little luck. Perhaps I was asking the wrong questions or perhaps there is a dearth of relevant material (unlikely). In any event, it seemed like this was best resolved by examining the front end functionality of the app and seeing exactly how and where it would be plugged into the backend. The backend models of course would need to inform this functionality. My thoughts are the following regarding the backend architecture.

  1. The user table should be created with the following attributes:

2. A match table should be created with the following attributes:

The status string attribute is intended to accept three values —denied, pending, confirmed.

3. Each match instance will be holding two foreign keys containing user_ids. The alias for these ids are requestor (the user that initiates a match instance) and a receiver (the other user). The requestor and receiver creates a self-referential relationship within the user class. This can be articulated with the following code in the user model:

4. This self reference relationship will thus need to be reflected in our match class model as well:

Right now, I’m setting aside all of the other relationships and functionality that we want to have for our users and matches. I might want to go back and rework this relationship later, after-all self referential tables so commonly used in social media apps can be tricky, but this is as good a place as any to start.

The following pseudocode steps essentially highlight the order of operations the user would take and what needs to happen in the for the app to produce the results the user is looking for.

  1. The user is able to see their potential matches.
Photo by Jamie Street on Unsplash

In order to first accomplish this, we’ll need to fetch an array of user ids or user instances from the backend that match a certain criteria. That criteria, while crucial to the app, isn’t really relevant for the purposes of this article. With that said it will be based on some filter logic that omits the current, primary user from the list and examines other users’ locations, interests, etc. I haven’t decided at this point if initially fetching and compiling ids instead of entire instances will ultimately be less costly, but I think to start with that and later fetch the entire instances of other users in bit-by-bit chucks when the user is swiping through will probably be less taxing on the system. With an array of ids, we can iterate through and fetch the instances of the other users when the primary user needs to have them displayed and we force an interaction (swiping). The primary user will only be able to see other users that:

  • They have not swiped/interacted with yet i.e. a match instance does not exist where one user is the requestor and the other is the receiver. It doesn’t matter who is the requestor or the receiver, but either should be checked.
  • A match instance exists where the other user is the requestor and the primary user is the receiver, the other user swiped right (or whatever the equivalent of that will be in my app — yet to be determined). The status value in this match instance is set to pending.

2. If the user swipes left (or whatever the equivalent is), a number of actions will be triggered.

  • If a match instance exists (where the status is pending), a patch request is sent to change the status to denied.
  • If a match instance does not exist, one is instantiated with the primary user as the requestor, the other user as the receiver, and the status set to denied.

It almost goes without saying, but once a match status is changed to denied, it will be recorded in the backend database, but it won’t be pulled to the frontend.

3. If the user swipes right (or whatever the equivalent is), a number of other actions will be triggered.

  • If a match instance exists (where the status is pending), a patch request is sent to change the status to confirmed.
  • If a match instance does not exist, one is instantiated with the primary user as the requestor, the other user as the receiver, and the status set to pending.

At this point, we have some data that we can work with. Confirmed matches will then be able to trigger message functionality (which is why we capture first_message_sent in the match model), as our match class has many messages and a message belongs to a match. It should be noted that this is a rough layout of the operation flow and once implement, changes may need to be made.

--

--