Video Conferencing System - Database Design
Database Architecture Overview
Copy ┌─────────────────────────────────────────────────────────────┐
│ Database Layer │
├─────────────────┬─────────────────┬─────────────────────────┤
│ PostgreSQL │ Redis │ Cassandra │
│ ( OLTP ) │ ( Cache / │ ( Analytics / │
│ │ Sessions ) │ Time Series ) │
├─────────────────┼─────────────────┼─────────────────────────┤
│ • Users │ • Active │ • Meeting Events │
│ • Meetings │ Sessions │ • Call Quality Metrics │
│ • Permissions │ • WebRTC State │ • Usage Analytics │
│ • Recordings │ • Chat Messages │ • Audit Logs │
└─────────────────┴─────────────────┴─────────────────────────┘PostgreSQL Schema (Primary Database)
Users Table
Copy CREATE TABLE users (
user_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR (255 ) UNIQUE NOT NULL ,
username VARCHAR (100 ) UNIQUE NOT NULL ,
display_name VARCHAR (200 ) NOT NULL ,
avatar_url TEXT,
timezone VARCHAR (50 ) DEFAULT 'UTC' ,
language VARCHAR (10 ) DEFAULT 'en' ,
account_type VARCHAR (20 ) DEFAULT 'basic' ,
status VARCHAR (20 ) DEFAULT 'active' ,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
last_login_at TIMESTAMP WITH TIME ZONE,
INDEX idx_users_email (email),
INDEX idx_users_username (username),
INDEX idx_users_status (status),
INDEX idx_users_created_at (created_at)
);Meetings Table
Copy CREATE TABLE meetings (
meeting_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
host_user_id UUID NOT NULL REFERENCES users(user_id),
title VARCHAR (500 ) NOT NULL ,
description TEXT,
meeting_type VARCHAR (20 ) NOT NULL ,
scheduled_start_time TIMESTAMP WITH TIME ZONE,
scheduled_end_time TIMESTAMP WITH TIME ZONE,
actual_start_time TIMESTAMP WITH TIME ZONE,
actual_end_time TIMESTAMP WITH TIME ZONE,
duration_minutes INTEGER ,
max_participants INTEGER DEFAULT 100 ,
require_password BOOLEAN DEFAULT FALSE ,
password_hash VARCHAR (255 ),
waiting_room_enabled BOOLEAN DEFAULT TRUE ,
recording_enabled BOOLEAN DEFAULT FALSE ,
auto_record BOOLEAN DEFAULT FALSE ,
allow_screen_share BOOLEAN DEFAULT TRUE ,
allow_chat BOOLEAN DEFAULT TRUE ,
allow_reactions BOOLEAN DEFAULT TRUE ,
mute_on_entry BOOLEAN DEFAULT FALSE ,
status VARCHAR (20 ) DEFAULT 'scheduled' ,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
INDEX idx_meetings_host (host_user_id),
INDEX idx_meetings_status (status),
INDEX idx_meetings_scheduled_start (scheduled_start_time),
INDEX idx_meetings_created_at (created_at)
);Meeting Participants Table
Copy CREATE TABLE meeting_participants (
participant_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
meeting_id UUID NOT NULL REFERENCES meetings(meeting_id),
user_id UUID REFERENCES users(user_id),
display_name VARCHAR (200 ) NOT NULL ,
email VARCHAR (255 ),
role VARCHAR (20 ) DEFAULT 'participant' ,
joined_at TIMESTAMP WITH TIME ZONE,
left_at TIMESTAMP WITH TIME ZONE,
duration_minutes INTEGER ,
is_muted BOOLEAN DEFAULT FALSE ,
is_video_on BOOLEAN DEFAULT TRUE ,
is_screen_sharing BOOLEAN DEFAULT FALSE ,
is_hand_raised BOOLEAN DEFAULT FALSE ,
connection_id VARCHAR (100 ),
ip_address INET,
user_agent TEXT,
status VARCHAR (20 ) DEFAULT 'invited' ,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
INDEX idx_participants_meeting (meeting_id),
INDEX idx_participants_user (user_id),
INDEX idx_participants_status (status),
INDEX idx_participants_joined_at (joined_at),
UNIQUE (meeting_id, user_id, joined_at)
);Recordings Table
Copy CREATE TABLE recordings (
recording_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
meeting_id UUID NOT NULL REFERENCES meetings(meeting_id),
recorded_by_user_id UUID NOT NULL REFERENCES users(user_id),
title VARCHAR (500 ) NOT NULL ,
description TEXT,
file_size_bytes BIGINT ,
duration_seconds INTEGER ,
storage_provider VARCHAR (50 ) NOT NULL ,
storage_bucket VARCHAR (200 ) NOT NULL ,
storage_key VARCHAR (500 ) NOT NULL ,
storage_region VARCHAR (50 ),
recording_type VARCHAR (20 ) NOT NULL ,
video_quality VARCHAR (20 ),
audio_quality VARCHAR (20 ),
processing_status VARCHAR (20 ) DEFAULT 'processing' ,
processing_started_at TIMESTAMP WITH TIME ZONE,
processing_completed_at TIMESTAMP WITH TIME ZONE,
processing_error TEXT,
visibility VARCHAR (20 ) DEFAULT 'private' ,
download_enabled BOOLEAN DEFAULT TRUE ,
password_protected BOOLEAN DEFAULT FALSE ,
password_hash VARCHAR (255 ),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
expires_at TIMESTAMP WITH TIME ZONE,
INDEX idx_recordings_meeting (meeting_id),
INDEX idx_recordings_recorded_by (recorded_by_user_id),
INDEX idx_recordings_status (processing_status),
INDEX idx_recordings_created_at (created_at),
INDEX idx_recordings_expires_at (expires_at)
);Chat Messages Table
Copy CREATE TABLE chat_messages (
message_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
meeting_id UUID NOT NULL REFERENCES meetings(meeting_id),
sender_user_id UUID REFERENCES users(user_id),
sender_name VARCHAR (200 ) NOT NULL ,
message_type VARCHAR (20 ) DEFAULT 'text' ,
content TEXT NOT NULL ,
formatted_content JSONB,
file_url TEXT,
file_name VARCHAR (500 ),
file_size_bytes INTEGER ,
file_type VARCHAR (100 ),
is_private BOOLEAN DEFAULT FALSE ,
recipient_user_id UUID REFERENCES users(user_id),
reply_to_message_id UUID REFERENCES chat_messages(message_id),
reactions JSONB DEFAULT '{}' ,
is_deleted BOOLEAN DEFAULT FALSE ,
deleted_at TIMESTAMP WITH TIME ZONE,
deleted_by_user_id UUID REFERENCES users(user_id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
INDEX idx_chat_meeting (meeting_id),
INDEX idx_chat_sender (sender_user_id),
INDEX idx_chat_created_at (created_at),
INDEX idx_chat_private (is_private, recipient_user_id),
INDEX idx_chat_deleted (is_deleted)
);Redis Schema (Cache & Sessions)
Active Sessions
Copy
SET session:{session_id} '{
"user_id" : "uuid" ,
"meeting_id" : "uuid" ,
"connection_id" : "webrtc_conn_id" ,
"joined_at" : "2024-01-15T10:30:00Z" ,
"is_muted" : false ,
"is_video_on" : true ,
"peer_connections" : ["pc1" , "pc2" ],
"ice_candidates" : [...],
"sdp_offer" : "..." ,
"sdp_answer" : "..."
}' EX 7200
SET meeting_room:{meeting_id} '{
"active_participants" : ["user1" , "user2" , "user3" ],
"participant_count" : 3 ,
"is_recording" : true ,
"screen_sharing_user" : "user2" ,
"chat_enabled" : true ,
"waiting_room_users" : ["user4" ],
"breakout_rooms" : {...}
}' EX 14400 Real-time Chat Cache
Copy
LPUSH chat:{meeting_id} '{
"message_id" : "uuid" ,
"sender_id" : "uuid" ,
"sender_name" : "John Doe" ,
"content" : "Hello everyone!" ,
"timestamp" : "2024-01-15T10:35:00Z" ,
"type" : "text"
}'
LTRIM chat:{meeting_id} 0 99
SET presence:{user_id} '{
"status" : "in_meeting" ,
"meeting_id" : "uuid" ,
"last_seen" : "2024-01-15T10:35:00Z" ,
"device_type" : "desktop"
}' EX 300 WebRTC Signaling Cache
Copy
LPUSH ice_candidates:{connection_id} '{
"candidate" : "candidate:1 1 UDP 2130706431 192.168.1.100 54400 typ host" ,
"sdpMLineIndex" : 0 ,
"sdpMid" : "audio"
}'
EXPIRE ice_candidates:{connection_id} 300
SET sdp_offer:{connection_id} '{
"type" : "offer" ,
"sdp" : "v=0\r \n o=- 123456789 2 IN IP4 127.0.0.1\r \n ..."
}' EX 300
SET sdp_answer:{connection_id} '{
"type" : "answer" ,
"sdp" : "v=0\r \n o=- 987654321 2 IN IP4 127.0.0.1\r \n ..."
}' EX 300 Cassandra Schema (Analytics & Time Series)
Meeting Events Table
Copy CREATE TABLE meeting_events (
meeting_id UUID ,
event_time TIMESTAMP ,
event_id UUID ,
event_type TEXT ,
user_id UUID ,
user_name TEXT ,
event_data MAP<TEXT , TEXT >,
PRIMARY KEY (meeting_id, event_time, event_id)
) WITH CLUSTERING ORDER BY (event_time DESC );Call Quality Metrics
Copy CREATE TABLE call_quality_metrics (
meeting_id UUID ,
participant_id UUID ,
metric_time TIMESTAMP ,
audio_bitrate INT ,
audio_packet_loss FLOAT ,
audio_jitter FLOAT ,
audio_rtt INT ,
video_bitrate INT ,
video_packet_loss FLOAT ,
video_frame_rate FLOAT ,
video_resolution TEXT ,
video_rtt INT ,
network_type TEXT ,
bandwidth_available INT ,
cpu_usage FLOAT ,
memory_usage INT ,
PRIMARY KEY ((meeting_id, participant_id), metric_time)
) WITH CLUSTERING ORDER BY (metric_time DESC );Usage Analytics
Copy CREATE TABLE daily_usage_stats (
date DATE,
metric_name TEXT ,
dimension_key TEXT , -- user_id, region, device_type, etc.
dimension_value TEXT ,
metric_value BIGINT,
PRIMARY KEY (date, metric_name, dimension_key, dimension_value)
);
-- Examples:
-- ('2024-01-15' , 'total_meetings' , 'region' , 'us-east-1' , 15000 )
-- ('2024-01-15' , 'total_participants' , 'device_type' , 'mobile' , 50000 )
-- ('2024-01-15' , 'meeting_duration_minutes' , 'user_id' , 'uuid' , 120 )Database Partitioning Strategy
PostgreSQL Partitioning
Copy
CREATE TABLE meetings_2024_01 PARTITION OF meetings
FOR VALUES FROM ('2024-01-01' ) TO ('2024-02-01' );
CREATE TABLE meetings_2024_02 PARTITION OF meetings
FOR VALUES FROM ('2024-02-01' ) TO ('2024-03-01' );
CREATE TABLE chat_messages_0 PARTITION OF chat_messages
FOR VALUES WITH (MODULUS 16 , REMAINDER 0 );
CREATE TABLE chat_messages_1 PARTITION OF chat_messages
FOR VALUES WITH (MODULUS 16 , REMAINDER 1 );Cassandra Partitioning
Copy
CREATE TABLE meeting_events_hourly (
meeting_id UUID ,
hour_bucket TIMESTAMP ,
event_time TIMESTAMP ,
event_id UUID ,
event_type TEXT ,
event_data MAP<TEXT , TEXT >,
PRIMARY KEY ((meeting_id, hour_bucket), event_time, event_id)
);Data Retention Policies
PostgreSQL Retention
Copy
DELETE FROM meetings
WHERE created_at < NOW() - INTERVAL '7 years'
AND status = 'ended' ;
DELETE FROM chat_messages
WHERE created_at < NOW() - INTERVAL '1 year' ;Redis Expiration
Session data: 2-4 hours TTL
Chat cache: 24 hours TTL
Presence data: 5 minutes TTL with heartbeat
WebRTC signaling: 5 minutes TTL
Cassandra TTL
Copy -- Insert with TTL for automatic cleanup
INSERT INTO call_quality_metrics (...)
VALUES (...) USING TTL 2592000 ; -- 30 days
INSERT INTO meeting_events (...)
VALUES (...) USING TTL 31536000 ; -- 1 yearBackup and Recovery
PostgreSQL Backup
Continuous WAL archiving to S3
Daily full backups with point-in-time recovery
Cross-region replication for disaster recovery
Automated backup testing and validation
Redis Persistence
RDB snapshots every 15 minutes
AOF (Append Only File) for durability
Redis Cluster with automatic failover
Memory optimization with appropriate eviction policies
Cassandra Backup
Incremental backups using snapshots
Cross-datacenter replication (RF=3 per DC)
Automated repair and consistency checks
Backup verification and restore testing