Belajar GraphQL - Project: Social Network with Real-Time Features
Episode 42 of 51

Belajar GraphQL - Project: Social Network with Real-Time Features

Episode 42 membangun platform social media: user profiles dan relationships, post creation dengan media upload, komentar dan reaksi, following-followers, timeline feed dengan pagination, notifikasi real-time, chat, hashtag, hingga strategi performa feed di skala besar.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Project kedua di fase real-world: platform social media dengan fitur lengkap dan real-time. Ini adalah salah satu tipe aplikasi paling menantang karena kombinasi data sosial kompleks, media upload, feed berskala besar, dan notifikasi instan.

Episode 42 membangunnya lapis demi lapis: fitur sosial inti, fitur real-time, fungsionalitas lanjutan, dan strategi performa untuk feed.

Core Social Features

User Profiles dan Relationships

Model relasi sosial di Prisma:

JSModel social graph
model User {
  id          Int    @id @default(autoincrement())
  username    String @unique
  displayName String
  avatarUrl   String?
  followers   Follow[]
  following   Follow[]
}
 
model Follow {
  followerId Int
  followingId Int
  createdAt  DateTime @default(now())
  @@id([followerId, followingId])
}

Relationship mengikuti polanya: Follow sebagai join table dengan composite primary key. Query followers dan following memakai pagination (episode 12) karena bisa berjumlah besar.

Post Creation dan Media Upload

Post dengan media memakai file upload (episode 17):

Mutation post dengan media
type Mutation {
  createPost(input: CreatePostInput!, media: [Upload!]): Post!
}
 
input CreatePostInput {
  body: String!
  hashtags: [String!]
}

Media diupload ke object storage (S3), dan URL-nya disimpan di post. Validasi tipe dan ukuran file diterapkan sebelum upload — sesuai checklist keamanan episode 17.

Komentar dan Reaksi

Komentar adalah tree (komentar bisa membalas komentar), dan reaksi memakai enum:

Schema komentar dan reaksi
type Comment {
  id: ID!
  body: String!
  parent: Comment
  replies: CommentConnection!
}
 
enum ReactionType {
  LIKE
  LOVE
  LAUGH
  SAD
  ANGRY
}
 
type Reaction {
  type: ReactionType!
  count: Int!
}

Komentar bertingkat dibatasi kedalamannya untuk performa; reaksi di-agregat dengan query group by.

Real-Time Features

Live Notifications dan Online Presence

Live notifications memakai subscription per user:

Subscription notifikasi
type Subscription {
  notificationReceived: Notification!
}
JSPublish notifikasi ke user tertentu
async function notifyUser(userId, notification) {
  await pubsub.publish(`NOTIFICATION:${userId}`, { notificationReceived: notification });
}

Online presence memakai pola presence dari episode 38: status online di-publish dan didengarkan user lain yang relevan.

Chat dan Live Comment Updates

Real-time chat memakai topik per room (episode 16). Live comment updates bisa memakai subscription per post — setiap komentar baru dipublish ke topik post tersebut. Untuk lalu lintas tinggi, batasi frekuensi atau agregasi singkat (misalnya update tiap beberapa detik).

Advanced Functionality

Search, Hashtag, dan Moderasi

  • Search users dan content: pakai full-text search database atau layanan seperti Meilisearch.
  • Hashtag system: ekstrak hashtag dari teks post saat create, simpan sebagai tabel.
  • Content moderation: filter otomatis (daftar kata, deteksi gambar) sebelum publish, dengan flag untuk review manual.
  • Privacy controls: isPrivate di user — post hanya terlihat follower yang disetujui.
  • Blocking dan reporting: block memfilter konten user di feed; report mengirim entri untuk moderasi.
Query hashtag
type Query {
  hashtag(tag: String!, first: Int!, after: String): PostConnection!
}

Privacy Filtering

Penerapan privacy memakai data filtering (episode 14): resolver feed menyaring post berdasarkan isPrivate dan relasi follow — user tidak boleh melihat konten privat orang yang bukan follower.

Performance at Scale

Feed Generation Strategies

Feed adalah masalah klasik social media. Strategi yang umum:

  • Fan-out on write: saat post dibuat, salin ID-nya ke timeline seluruh follower — baca cepat, tulis berat.
  • Fan-out on read: feed dihitung saat dibaca — tulis ringan, baca berat.
  • Hybrid: fan-out untuk follower aktif, on-read untuk sisanya.
JSFeed via Redis list
const followers = await ctx.db.follows.findMany({ where: { followingId: userId } });
for (const f of followers) {
  await ctx.redis.lpush(`feed:${f.followerId}`, postId);
}

Pilih strategi sesuai skala; mulai dari fan-out on read yang sederhana, lalu evolusi.

Caching dan Optimasi Database

  • Cache konten populer di Redis dengan TTL — misalnya LPUSH feed:123 postId pada pola feed.
  • Database optimization: index di authorId, createdAt, dan join table.
  • Image CDN: sajikan media lewat CDN dengan ukuran yang sesuai perangkat.

Feed yang dipaginasi dengan cursor (episode 12) dikombinasikan dengan cache membuat scroll pengalaman terasa mulus.

Penutup

Inti yang harus dibawa pulang:

  • Follow dan komentar bertingkat dimodelkan dengan join table dan tree.
  • Media upload memakai S3 dengan validasi ketat.
  • Notifikasi dan chat memakai subscription per user dan per room.
  • Privacy controls dan blocking diterapkan lewat data filtering.
  • Feed memakai fan-out on write, on read, atau hybrid sesuai skala.
  • Index, cache, dan CDN menjaga performa feed tetap baik.

Di episode 43 selanjutnya kalian akan mempelajari proyek multi-tenant SaaS — arsitektur multi-tenancy dengan database per tenant versus shared, tenant context propagation, manajemen organisasi dengan undangan dan role, billing dengan Stripe subscriptions, hingga fitur enterprise seperti SSO dan audit logs. Aplikasi SaaS enterprise kalian akan siap!

Belajar GraphQL - Project: Social Network with Real-Time Features | Belajar GraphQL