Facebook Pixel

DevTinder Database Schema Overview

DevTinder has a clear data model. Here is the schema overview for its main collections.

DevTinder Database Schema Overview

DevTinder uses MongoDB with Mongoose. Here is the schema overview for its main collections.

User

_id: ObjectId
firstName: String, required
lastName: String, required
email: String, required, unique, lowercase
passwordHash: String, required
age: Number, min 18
gender: String, enum ['male', 'female', 'other']
photoUrl: String
about: String, default 'Hey there! I am using DevTinder.'
skills: [String]
createdAt: Date
updatedAt: Date

Index: unique on email. Notes: Never return passwordHash in responses.

ConnectionRequest

_id: ObjectId
fromUserId: ObjectId, ref 'User', required
toUserId: ObjectId, ref 'User', required
status: String, enum ['ignored', 'interested', 'accepted', 'rejected'], required
createdAt: Date
updatedAt: Date

Index: compound unique on (fromUserId, toUserId). Notes: Prevents duplicate swipe attempts.

Connection (Match)

_id: ObjectId
user1Id: ObjectId, ref 'User', required
user2Id: ObjectId, ref 'User', required
createdAt: Date

Index: unique on (user1Id, user2Id) with user1Id < user2Id ordering. Prevents duplicate matches in either direction. Notes: A match is created when both users swipe interested on each other.

Message

_id: ObjectId
connectionId: ObjectId, ref 'Connection', required
senderId: ObjectId, ref 'User', required
text: String, required
createdAt: Date

Index: compound on (connectionId, createdAt). For fast room history loads.

Payment

_id: ObjectId
userId: ObjectId, ref 'User', required
orderId: String, required (Razorpay order id)
paymentId: String
amount: Number, required
currency: String, default 'INR'
status: String, enum ['created', 'paid', 'failed'], required
createdAt: Date

Index: on userId for the user's payment history.

Subscription

_id: ObjectId
userId: ObjectId, ref 'User', required, unique
plan: String, enum ['free', 'premium']
validUntil: Date
createdAt: Date

Design Notes

  • Use refs, not embedded arrays, for relations with large N (messages, connections).
  • Use populate to join on read.
  • Keep documents small. Avoid unbounded array growth.
  • Index the queries you actually run, not every field.

The Takeaway

DevTinder main collections: User, ConnectionRequest, Connection, Message, Payment, Subscription. Index the queries you run. Use refs for large-N relations. Keep documents small. Never return passwordHash.

User, ConnectionRequest, Connection (match), Message, Payment, and Subscription. Each handles a specific module: users, swipes, matches, chat, payments, and plan status.

It prevents duplicate swipe attempts (a user cannot swipe on the same target twice) and speeds up the most common query: "did A already swipe on B?" Compound unique indexes serve both integrity and performance.

A unique index on (user1Id, user2Id) where user1Id < user2Id ordering. This makes a match between A and B have one canonical form, so two requests cannot create the same match.

Embedded arrays grow documents unboundedly. MongoDB has a 16MB document limit, and large arrays slow down every read. Refs keep documents small and let you paginate.

Email (unique) on User. (fromUserId, toUserId) compound unique on ConnectionRequest. (user1Id, user2Id) unique on Connection. (connectionId, createdAt) on Message. userId on Payment. Index the queries you actually run, not every field.

Ready to master Node.js completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.