Xây Dựng Ứng Dụng Social Media Với Supabase Tính Năng Follow Và Feed

05/03/2026 P T P Chung 7 phút đọc 0 bình luận

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.

Quảng cáo

728x90 Bottom Advertisement

Thay thế bằng mã Google AdSense

Chia sẻ bài viết

Facebook Twitter

Bình luận

Chia sẻ ý kiến của bạn về bài viết này

Viết bình luận

Bình luận của bạn sẽ được kiểm duyệt trước khi hiển thị

Chưa có bình luận nào

Hãy là người đầu tiên bình luận về bài viết này!