News Feed (Facebook/Twitter) ডিজাইন
- ●News feed হলো তুমি যাদের follow করো তাদের post একসাথে সাজিয়ে দেখানো — মূল চ্যালেঞ্জ কোটি কোটি user-এর feed দ্রুত তৈরি করা।
- ●দুটো কৌশল — fan-out on write (post-এর সময় সবার feed-এ ছড়িয়ে দাও) আর fan-out on read (feed খোলার সময় টেনে আনো); বাস্তবে hybrid ব্যবহার হয়।
- ●Celebrity-দের কোটি follower থাকায় তাদের post সবার feed-এ লেখা অসম্ভব, তাই তাদের post read-এর সময় merge করা হয়।
Facebook খুললেই বা Twitter (X)-এ ঢুকলেই যে post-গুলোর তালিকা ভেসে ওঠে — তুমি যাদের follow করো তাদের সাম্প্রতিক post সাজানো — সেটাই News Feed। দেখতে সরল মনে হলেও, কোটি কোটি user-এর জন্য মিলিসেকেন্ডে feed তৈরি করা system design-এর অন্যতম কঠিন সমস্যা। চলো ধাপে ধাপে ডিজাইন করি।
১. সমস্যা বোঝা (Requirements)
Functional requirements:
- User post করতে পারবে (text, ছবি, video)।
- User অন্যদের follow করতে পারবে।
- User তার news feed দেখবে — যাদের follow করে তাদের post, সময় বা প্রাসঙ্গিকতা অনুসারে সাজানো।
- Feed-এ pagination থাকবে (নিচে scroll করলে আরও আসবে — infinite scroll)।
Non-functional requirements:
- Low latency — feed খুলতে হবে চোখের পলকে (~200ms)। এটাই সবচেয়ে বড় চ্যালেঞ্জ।
- High availability — feed সবসময় চালু থাকবে।
- Eventual consistency গ্রহণযোগ্য — তোমার বন্ধুর post তোমার feed-এ আসতে কয়েক সেকেন্ড দেরি হলে সমস্যা নেই।
- Scalability — শত কোটি user, প্রতিদিন কোটি কোটি post।
News feed অনেকটা পত্রিকার মতো। তুমি চাইলে প্রতিদিন সকালে নিজে সব ঘটনা খুঁজে বেড়াতে পারো (ধীর), অথবা পত্রিকা আগেই সব খবর গুছিয়ে তোমার দরজায় দিয়ে যেতে পারে (দ্রুত)। Fan-out on write হলো সেই দরজায়-পৌঁছে-দেওয়া পত্রিকা — feed আগেই বানানো থাকে।
২. স্কেল আন্দাজ (Estimation)
ধরি দৈনিক সক্রিয় user (DAU) ৩০ কোটি, প্রত্যেকে গড়ে ২টা post করে আর দিনে ৫ বার feed খোলে।
DAU = 300,000,000
Post/দিন (write) = 300M × 2 = 600M posts/day
Write QPS = 600M / 86,400 ≈ 7,000 posts/sec
Feed খোলা (read)/দিন = 300M × 5 = 1.5 বিলিয়ন/day
Read QPS = 1.5B / 86,400 ≈ 17,000 feed-reads/sec → peak ~50,000
Read : Write ≈ 100 : 1 → প্রবলভাবে read-heavy
Fan-out খরচ (গড় ২০০ follower ধরে):
7,000 post/sec × 200 follower = 1.4M feed-writes/sec ← এটাই আসল চাপ!
মূল উপলব্ধি — read অনেক বেশি, কিন্তু fan-out write (একটা post অনেক feed-এ ছড়ানো) আসল কঠিন জায়গা। আর celebrity-র কোটি follower থাকলে এই সংখ্যা বিস্ফোরিত হয়।
৩. API ডিজাইন
POST /api/v1/posts
body: { "userId": "u1", "content": "...", "media": [...] }
resp: 201 { "postId": "p123", "createdAt": "..." }
GET /api/v1/feed?userId=u1&cursor=<last_post_id>&limit=20
resp: 200 { "posts": [ {postId, author, content, ...}, ... ], "nextCursor": "p99" }
POST /api/v1/follow
body: { "followerId": "u1", "followeeId": "u2" }
resp: 200
খেয়াল করো feed-এ cursor-based pagination — offset নয়। কারণ feed সবসময় বদলায়; cursor (শেষ দেখা post-এর id) ব্যবহার করলে নতুন post এলেও duplicate বা skip হয় না।
৪. ডেটা মডেল
প্রধান কয়েকটা table/collection:
Posts
| Field | Type | বর্ণনা |
|---|---|---|
| post_id | string PK | ইউনিক id |
| user_id | string | কে post করেছে |
| content | text | লেখা/মিডিয়ার রেফারেন্স |
| created_at | timestamp | সময় (sorting-এর জন্য) |
Follows
| Field | Type | বর্ণনা |
|---|---|---|
| follower_id | string | কে follow করছে |
| followee_id | string | কাকে follow করছে |
Feed cache (precomputed, Redis-এ)
| Field | Type | বর্ণনা |
|---|---|---|
| user_id | string key | feed-এর মালিক |
| post_ids | list | সাজানো post id-র তালিকা (newest first) |
SQL না NoSQL? Post আর follow সম্পর্ক relational, তাই সেখানে SQL বা wide-column NoSQL (Cassandra) দুটোই চলে — কিন্তু বিশাল write আর scale-এর জন্য সাধারণত NoSQL/Cassandra বেছে নেওয়া হয়। আর precomputed feed রাখা হয় Redis-এ (list structure), যাতে read instant হয়। এখানে আমরা ইচ্ছাকৃতভাবে Denormalization করি — মানে join এড়াতে data কিছুটা copy/precompute করে রাখি, যাতে read-এর সময় হিসাব না করতে হয়।
৫. হাই-লেভেল ডিজাইন
Component:
- Client, Load Balancer, App servers (stateless)।
- Post service — নতুন post নেয়, DB-তে save করে, fan-out শুরু করে।
- Fan-out service + Message Queue — post-কে follower-দের feed-এ ছড়ায় (asynchronous, background-এ)।
- Feed cache (Redis) — প্রতিটা user-এর precomputed feed।
- Feed service — feed পড়ার request সামলায়।
- CDN — ছবি/video serve করে, যাতে heavy media app server না ছোঁয়।
Write flow (post করা):
- Post service post-টা DB-তে save করে।
- একটা message queue-তে "fan-out job" পাঠায় (synchronous response দ্রুত রাখতে)।
- Fan-out worker follower-দের তালিকা নিয়ে প্রত্যেকের feed cache-এ এই post id যোগ করে।
Read flow (feed দেখা):
- Feed service Redis থেকে user-এর precomputed post id list নেয় (instant)।
- post id দিয়ে post-এর পূর্ণ বিবরণ আনে (এগুলোও cache করা)।
- ranked/sorted করে pagination সহ ফেরত দেয়।
৬. গভীরে (Deep Dive)
৬.১ Fan-out on Write vs Fan-out on Read
এটাই এই system-এর হৃদয়।
Fan-out on write (push model): কেউ post করলেই সেটা তার সব follower-এর feed cache-এ আগেভাগে লিখে দেওয়া হয়।
- সুবিধা: feed পড়া অসম্ভব দ্রুত — শুধু নিজের তৈরি তালিকা পড়ে নাও।
- অসুবিধা: write ব্যয়বহুল — ২০০ follower মানে ২০০ feed update। আর celebrity হলে কোটি update।
Fan-out on read (pull model): feed কিছু আগে থেকে বানানো নেই; user feed খুললে তখন সে যাদের follow করে তাদের সাম্প্রতিক post টেনে এনে merge করা হয়।
- সুবিধা: write সস্তা (post শুধু একবার লেখা হয়)।
- অসুবিধা: read ধীর ও ব্যয়বহুল — প্রতিবার অনেকের post টেনে sort করতে হয়।
| দিক | Fan-out on Write (push) | Fan-out on Read (pull) |
|---|---|---|
| Read গতি | খুব দ্রুত | ধীর |
| Write খরচ | বেশি | কম |
| Celebrity-তে | ভয়ংকর (write storm) | ঠিকঠাক |
| Active user | আদর্শ | অপচয় (যে feed দেখেই না) |
৬.২ Celebrity সমস্যা ও Hybrid সমাধান
একজন celebrity-র ১ কোটি follower থাকলে, তার একটা post pure fan-out on write-এ ১ কোটি feed update দাবি করে — বিশাল write storm আর বিলম্ব। আবার সাধারণ user-এর জন্য fan-out on read অপচয়।
সমাধান — Hybrid:
- সাধারণ user (অল্প follower) → fan-out on write। তাদের post follower-দের feed-এ push করা হয়।
- Celebrity (বিশাল follower) → তাদের post fan-out করা হয় না। follower যখন feed খোলে, তখন সে যে celebrity-দের follow করে তাদের সাম্প্রতিক post live টেনে এনে নিজের precomputed feed-এর সাথে merge করে।
এতে দুই দুনিয়ার ভালোটা পাওয়া যায় — সাধারণ post-এ দ্রুত read, আর celebrity-তে write storm এড়ানো।
সব নিষ্ক্রিয় user-এর জন্য fan-out on write অপচয় — যে user ৬ মাস login করে না, তার feed cache update করে CPU ও memory নষ্ট কোরো না। সমাধান: শুধু active user-দের feed precompute করো, নিষ্ক্রিয়দেরটা pull (read) মডেলে রাখো।
৬.৩ Ranking ও Pagination
পুরোনো feed শুধু সময় অনুসারে (newest first) সাজাত। আধুনিক feed ranking ব্যবহার করে — কোন post বেশি প্রাসঙ্গিক তা ঠিক করতে engagement, সম্পর্কের ঘনিষ্ঠতা, post-এর বয়স ইত্যাদি একটা score-এ মিলিয়ে সাজায়। আর pagination cursor-based — শেষ দেখা post-এর id দিয়ে পরের ব্যাচ আনা হয়, যাতে নতুন post এলেও duplicate/skip না হয়।
৭. বটলনেক ও স্কেলিং
- Read load — feed cache (Redis) আর post cache দিয়ে সামলাও; এটাই সবচেয়ে বড় কিন্তু সবচেয়ে cache-friendly।
- Fan-out write storm — message queue + অনেক worker দিয়ে asynchronous করো, যাতে post করা slow না হয়। celebrity-দের hybrid-এ রাখো।
- Database scaling — post আর follow data sharding (user_id দিয়ে) + read replica দিয়ে scale করো।
- Media — ছবি/video CDN থেকে serve করো, app server থেকে নয়।
- Hot key — viral post বা celebrity feed আলাদা cache/replica-তে রাখো যাতে এক node-এ চাপ না জমে।
৮. সারসংক্ষেপ
News feed-এর পুরো খেলা একটাই trade-off ঘিরে — feed কখন বানাবে: post করার সময় (push, দ্রুত read) নাকি feed খোলার সময় (pull, সস্তা write)। বাস্তব system hybrid ব্যবহার করে — সাধারণ user-এ push, celebrity-তে pull — সাথে precomputed feed cache, denormalization, async fan-out queue, ranking আর CDN।
Interviewer সবচেয়ে বেশি দেখতে চায় তুমি fan-out on write vs read-এর trade-off স্পষ্ট করতে পারো কিনা, এবং celebrity সমস্যাটা চিনে hybrid সমাধান দিতে পারো কিনা। "সবার জন্য একই কৌশল চলবে না" — এই অন্তর্দৃষ্টিটাই তোমাকে আলাদা করে দেবে।
মিনি কুইজ
1. Fan-out on write মানে কী?
2. Celebrity (কোটি follower) এর ক্ষেত্রে pure fan-out on write কেন সমস্যা?
3. Hybrid approach কী করে?