Overview
Jefftube uses PostgreSQL 16 with Drizzle ORM for type-safe database operations. The schema is defined inserver/src/db/schema.ts and consists of five main tables:
videos- Video metadata and statisticsusers- User accounts (IP-based)comments- User comments on videoscommentLikes- Likes/dislikes on commentsvideoLikes- Likes/dislikes on videos
Entity Relationship Diagram
Table Schemas
videos
Stores video metadata and aggregated statistics.- Schema
- Indexes
- TypeScript Type
- Relations
Defined in
schema.ts:4-16:| Column | Type | Constraints | Description |
|---|---|---|---|
id | varchar(50) | PRIMARY KEY | Filename without extension (e.g., “EFTA01683563”) |
title | varchar(255) | nullable | Video title |
filename | varchar(255) | NOT NULL, UNIQUE | Original filename with extension |
length | integer | NOT NULL | Video duration in seconds |
hasThumbnail | boolean | NOT NULL, DEFAULT false | Whether a thumbnail exists |
views | integer | NOT NULL, DEFAULT 0 | Total view count |
likes | integer | NOT NULL, DEFAULT 0 | Net likes (likes - dislikes) |
is_shorts | boolean | NOT NULL, DEFAULT false | Whether video appears in Shorts feed |
playlist | varchar(100) | nullable | Playlist identifier (e.g., “elevator-cam”) |
users
Stores user accounts created anonymously via IP address hashing.- Schema
- Privacy
- TypeScript Type
- Relations
Defined in
schema.ts:18-23:| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PRIMARY KEY, DEFAULT random | Unique user identifier |
ipHash | varchar(64) | NOT NULL, UNIQUE | SHA-256 hash of IP address |
username | varchar(50) | NOT NULL | Display name (user-chosen) |
createdAt | timestamp | NOT NULL, DEFAULT now() | Account creation time |
comments
Stores comments and replies in a self-referential tree structure.- Schema
- Indexes
- TypeScript Type
- Relations
Defined in
Cascade Behavior:
schema.ts:25-35:| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PRIMARY KEY, DEFAULT random | Unique comment identifier |
videoId | varchar(50) | NOT NULL, FK → videos.id | Video being commented on |
userId | uuid | NOT NULL, FK → users.id | Author of the comment |
parentId | uuid | nullable, FK → comments.id | Parent comment (null for top-level) |
content | text | NOT NULL | Comment text |
createdAt | timestamp | NOT NULL, DEFAULT now() | When comment was posted |
- If a video is deleted → all its comments are deleted
- If a user is deleted → all their comments are deleted
commentLikes
Tracks user likes/dislikes on comments.- Schema
- Indexes
- TypeScript Type
- Relations
Defined in
Cascade Behavior:
schema.ts:37-45:| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PRIMARY KEY, DEFAULT random | Unique like identifier |
commentId | uuid | NOT NULL, FK → comments.id | Comment being liked |
userId | uuid | NOT NULL, FK → users.id | User who liked |
isLike | boolean | NOT NULL | true = like, false = dislike |
createdAt | timestamp | NOT NULL, DEFAULT now() | When action was performed |
- If comment is deleted → all its likes are deleted
- If user is deleted → all their likes are deleted
videoLikes
Tracks user likes/dislikes on videos.- Schema
- Indexes
- TypeScript Type
- Relations
Defined in
Cascade Behavior:
schema.ts:47-55:| Column | Type | Constraints | Description |
|---|---|---|---|
id | uuid | PRIMARY KEY, DEFAULT random | Unique like identifier |
videoId | varchar(50) | NOT NULL, FK → videos.id | Video being liked |
userId | uuid | NOT NULL, FK → users.id | User who liked |
isLike | boolean | NOT NULL | true = like, false = dislike |
createdAt | timestamp | NOT NULL, DEFAULT now() | When action was performed |
- If video is deleted → all its likes are deleted
- If user is deleted → all their likes are deleted
Database Operations
Connection
The database connection is configured indrizzle.config.ts:
Migrations
Generate migration
After modifying This creates a SQL file in the
schema.ts, generate a migration file:drizzle/ directory.Seeding
The seed script (src/db/seed.ts) populates the database with video data.
- Run Seed
- What it does
- Example Data Flow
Common Queries
Database Tools
Drizzle Studio
Launch a web-based database GUI:https://local.drizzle.studio where you can:
- Browse tables and data
- Run queries
- Edit records
- View relationships
PostgreSQL Docker Container
- Start
- Stop
- Reset
- Connect via psql
Performance Considerations
Indexes
The schema includes strategic indexes for common queries:| Index | Purpose | Query Pattern |
|---|---|---|
videos_views_idx | Sort by popularity | ORDER BY views DESC |
comments_video_parent_created | Fetch comment threads | WHERE video_id = ? AND parent_id IS NULL |
comments_video_user_created | User’s comments on video | WHERE video_id = ? AND user_id = ? |
comment_user_unique | Prevent duplicate likes | WHERE comment_id = ? AND user_id = ? |
video_user_unique | Prevent duplicate likes | WHERE video_id = ? AND user_id = ? |
Query Optimization Tips
Use selective columns
Use selective columns
Instead of:Use:
Paginate large result sets
Paginate large result sets
Use joins for related data
Use joins for related data
Batch inserts
Batch inserts
The seed script demonstrates efficient batch inserts:
Schema Modifications
When you need to modify the schema:Edit schema.ts
Make your changes to
server/src/db/schema.ts.Example: Add a description field to videos:Backup & Restore
Backup
Restore
Next Steps
Setup Guide
Set up your development environment
Architecture
Learn about the overall system architecture