Skip to content

Instantly share code, notes, and snippets.

@isocroft
Last active January 29, 2026 06:14
Show Gist options
  • Select an option

  • Save isocroft/03eec56bf6db1ca6363b6f1a2b51fc33 to your computer and use it in GitHub Desktop.

Select an option

Save isocroft/03eec56bf6db1ca6363b6f1a2b51fc33 to your computer and use it in GitHub Desktop.
A database schema for a Tinder-clone dating app using either MySQL, SQLite or PostgreSQL as primary database
-- MySQL v8.0.16
-- PostgresSQL v16.9.2
CREATE DATABASE IF NOT EXISTS `test`
DEFAULT CHARACTER SET utf8 -- utf8mb4
DEFAULT COLLATE utf8_general_ci; -- utf8mb4_unicode_ci
SET default_storage_engine = INNODB;
-- USERS Table: Core authentication information
CREATE TABLE user_details (
id bigint NOT NULL,
email varchar(100) UNIQUE NOT NULL,
password_hash varchar(255) NOT NULL,
created_at timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
last_login timestamp WITH TIME ZONE,
PRIMARY KEY (id)
);
-- PROFILES Table: Detailed personal information
CREATE TABLE user_accounts (
id bigint NOT NULL,
first_name varchar(50) NOT NULL,
last_name varchar(50) NOT NULL,
bio text,
date_of_birth date NOT NULL,
gender enum('male', 'female', 'non-binary') NOT NULL,
location_country char(2),
is_active tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES user_details(id) ON DELETE CASCADE
);
-- USER_PHOTOS Table: Store links to user photos
CREATE TABLE user_photos (
id bigint NOT NULL,
user_id bigint NOT NULL ,
photo_url varchar(255) NOT NULL,
is_profile_pic tinyint(1) NOT NULL DEFAULT 0,
uploaded_at timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES user_details(id) ON DELETE CASCADE
);
-- INTERESTS Table: Master list of all possible interests
CREATE TABLE user_interests (
id bigint NOT NULL,
interest_name varchar(50) UNIQUE NOT NULL,
PRIMARY KEY (id)
);
-- USER_WITH_INTERESTS Table: Many-to-many relationship between users and interests
CREATE TABLE user_with_interests (
user_id bigint NOT NULL ,
interest_id bigint NOT NULL,
PRIMARY KEY (user_id, interest_id),
FOREIGN KEY (user_id) REFERENCES user_details(id) ON DELETE CASCADE,
FOREIGN KEY (interest_id) REFERENCES user_interests(id) ON DELETE CASCADE
);
-- SWIPES Table: Track user interactions (likes/dislikes)
CREATE TABLE swipes (
swipe_id bigint NOT NULL,
swiper_id bigint NOT NULL,
swipee_id bigint NOT NULL,
swipe_type enum('like', 'dislike') NOT NULL,
created_at timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (swiper_id, swipee_id) -- Ensures a user can only swipe on another user once
PRIMARY KEY (id),
FOREIGN KEY (swiper_id) REFERENCES user_details(id) ON DELETE CASCADE,
FOREIGN KEY (swipee_id) REFERENCES user_details(id) ON DELETE CASCADE
);
-- MATCHES Table: Store successful matches (both users swiped 'like')
CREATE TABLE matches (
id bigint NOT NULL,
matcher_user_id bigint NOT NULL,
matchee_user_id bigint NOT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- Enforces that a match only exists once, regardless of user order
UNIQUE (LEAST(matcher_user_id, matchee_user_id), GREATEST(matcher_user_id, matchee_user_id)),
PRIMARY KEY (id),
FOREIGN KEY (matcher_user_id) REFERENCES use_details(id) ON DELETE CASCADE,
FOREIGN KEY (matchee_user_id) REFERENCES use_details(id) ON DELETE CASCADE
);
-- MESSAGES Table: In-app messaging
CREATE TABLE messages (
id bigint NOT NULL,
match_id bigint NOT NULL,
sender_id bigint NOT NULL ,
recipient_id UUID NOT NULL REFERENCES users(user_id),
message text NOT NULL,
sent_at timestamp WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_read tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (id),
FOREIGN KEY (match_id) REFERENCES matches(id) ON DELETE NO ACTION,
FOREIGN KEY (sender_id) REFERENCES user_details(id) ON DELETE NO ACTION,
FOREIGN KEY (recipient_id) REFERENCES user_details(id) ON DELETE NO ACTION,
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment