Tại sao nên chọn Supabase cho ứng dụng social media?
Supabase là một nền tảng Backend-as-a-Service (BaaS) mã nguồn mở, cung cấp cơ sở dữ liệu PostgreSQL đầy đủ tính năng, xác thực người dùng, lưu trữ tệp và API tự động. Với social media, nơi dữ liệu liên tục được tạo ra và cần xử lý thời gian thực, Supabase tỏ ra phù hợp nhờ khả năng scale nhanh, bảo mật cao và chi phí hợp lý so với các giải pháp truyền thống.
Thiết kế cơ sở dữ liệu
Một ứng dụng social media cơ bản cần các bảng chính sau:
- users: lưu thông tin người dùng. - follows: ghi lại mối quan hệ follow giữa các users (follower_id, following_id). - posts: chứa nội dung bài viết (user_id, content, created_at). - likes: lưu lượt thích của user cho mỗi post (user_id, post_id). - comments: chứa bình luận (user_id, post_id, content, created_at).
Ví dụ schema cho bảng follows:
CREATE TABLE follows (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
follower_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
following_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE (follower_id, following_id)
);
Chỉ mục trên follower_id và following_id giúp truy vấn nhanh hơn khi hiển thị feed.
Xây dựng tính năng follow
Để người dùng có thể follow/unfollow, ta cần các hàm lưu trữ (stored procedures) để đảm bảo tính nguyên tử và bảo mật:
CREATE OR REPLACE FUNCTION toggle_follow(
follower_id_in UUID,
following_id_in UUID
)
RETURNS TABLE (
following BOOLEAN,
success BOOLEAN,
message TEXT
)
AS $$
BEGIN
IF follower_id_in = following_id_in THEN
RETURN QUERY SELECT FALSE, FALSE, 'Không thể follow chính mình';
ELSIF EXISTS (
SELECT 1 FROM follows
WHERE follower_id = follower_id_in AND following_id = following_id_in
) THEN
DELETE FROM follows
WHERE follower_id = follower_id_in AND following_id = following_id_in;
RETURN QUERY SELECT FALSE, TRUE, 'Đã unfollow';
ELSE
INSERT INTO follows (follower_id, following_id)
VALUES (follower_id_in, following_id_in);
RETURN QUERY SELECT TRUE, TRUE, 'Đã follow';
END IF;
END;
$$ LANGUAGE plpgsql;
Frontend có thể gọi hàm này qua Supabase client:
const { data, error } = await supabase.rpc('toggle_follow', {
follower_id_in: userId,
following_id_in: targetUserId
});
Tạo feed thời gian thực
Feed của người dùng là tập hợp các bài viết từ những người họ đang follow. Cách đơn giản nhất là query trực tiếp:
SELECT p.*, u.username, u.avatar_url
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE p.user_id IN (
SELECT following_id FROM follows
WHERE follower_id = 'current_user_id'
)
ORDER BY p.created_at DESC
LIMIT 20;
Tuy nhiên, với lượng dữ liệu lớn, nên dùng materialized view để cache kết quả:
Quảng cáo
300x250 In-Content Advertisement
CREATE MATERIALIZED VIEW user_feed AS
SELECT p.*, u.username, u.avatar_url, f.follower_id
FROM posts p
JOIN users u ON p.user_id = u.id
JOIN follows f ON p.user_id = f.following_id;
CREATE UNIQUE INDEX idx_user_feed_id ON user_feed (follower_id, id);
Materialized view cần refresh định kỳ:
REFRESH MATERIALIZED VIEW CONCURRENTLY user_feed;
Realtime và thông báo
Supabase cung cấp WebSocket giúp cập nhật feed gần như tức thì. Đăng ký subscription trên bảng posts:
const posts = supabase
.channel('posts')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'posts'
}, (payload) => {
// Cập nhật feed
})
.subscribe();
Để thông báo khi có like/comment, có thể dùng Row Level Security (RLS) để chỉ cho phép user xem/sửa dữ liệu của mình, đồng thời kích hoạt webhook hoặc hàm lưu trữ để gửi notification.
Tối ưu hiệu năng
- Chỉ mục hợp lý: tạo index trên các cột join và where (follower_id, created_at).
- Phân trang: dùng LIMIT + OFFSET hoặc keyset pagination với created_at để tránh lag khi scroll.
- Cache: dùng Supabase Edge Functions hoặc Redis để cache feed trong vài giây.
- Denormalize: lưu thêm count_followers, count_posts vào users để giảm query.
Bảo mật và quyền riêng tư
Kích hoạt RLS để đảm bảo user chỉ truy cập dữ liệu được phép:
ALTER TABLE follows ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can follow/unfollow" ON follows
FOR ALL USING (auth.uid()::text IN (follower_id, following_id));
Kết luận
Xây dựng ứng dụng social media với Supabase không chỉ nhanh chóng nhờ các tính năng có sẵn như auth, realtime, lưu trữ, mà còn bảo mật và dễ scale. Tuy nhiên, cần chú ý tối ưu query, cache hợp lý và thiết kế schema chuẩn để đảm bảo trải nghiệm mượt mà khi lượng người dùng tăng cao. Với những bước trên, bạn đã có nền tảng vững chắc để phát triển một mạng xã hội riêng của mình.