Social & Communication১২ মিনিট পাঠ

চ্যাট সিস্টেম ডিজাইন (Design a Chat System)

লাখ লাখ মানুষের জন্য রিয়েল-টাইম মেসেজিং — তাৎক্ষণিকভাবে ডেলিভারড
scope:বাস্তব জগতের সিস্টেম (Real-World System)difficulty:মাঝারি-অ্যাডভান্সড

রিকোয়ারমেন্ট বা প্রয়োজনীয়তাগুলো বোঝা

আমরা হোয়াটসঅ্যাপ (WhatsApp), স্ল্যাক (Slack) বা ডিসকর্ডের (Discord) মতো একটি চ্যাট সিস্টেম ডিজাইন করতে যাচ্ছি। চলুন সঠিক প্রশ্নগুলো করার মাধ্যমে শুরু করি।

ফাংশনাল রিকোয়ারমেন্ট (ব্যবহারিক প্রয়োজনীয়তা):

  • ১:১ মেসেজিং (1:1 messaging) — আনিকা রাফিকে একটি মেসেজ বা বার্তা পাঠাবে। রাফি সেটি (প্রায়) তাৎক্ষণিকভাবে দেখতে পাবে।
  • গ্রুপ চ্যাট (Group chat) — একটি গ্রুপে সর্বোচ্চ ৫০০ জন সদস্য থাকতে পারবে।
  • অনলাইন/অফলাইন স্ট্যাটাস (Online/offline status) — বর্তমানে কারা সক্রিয় বা অ্যাক্টিভ আছে তা দেখতে পাওয়া যাবে।
  • রিড রিসিট (Read receipts) — আপনার মেসেজ কখন ডেলিভার (deliver) হয়েছে এবং কখন তা দেখা বা পড়া হয়েছে তা জানতে পারবেন।
  • পুশ নোটিফিকেশন (Push notifications) — যেসব ব্যবহারকারী অফলাইনে আছে তাদের নোটিফাই বা অবহিত করা হবে।
  • মেসেজ হিস্টোরি (Message history) — পুরনো মেসেজগুলো দেখতে স্ক্রল করে পেছনে যাওয়ার ব্যবস্থা থাকবে।

নন-ফাংশনাল রিকোয়ারমেন্ট (অ-ব্যবহারিক প্রয়োজনীয়তা):

  • লো ল্যাটেন্সি (Low latency): মেসেজগুলো ২০০ মিলিসেকেন্ডের (< 200ms) মধ্যে পৌঁছাতে হবে (যেন রিয়েল-টাইম বা সাথে সাথে কথা বলার অনুভূতি হয়)।
  • রিলায়্যাবিলিটি (Reliability): মেসেজ কখনোই হারিয়ে যাওয়া যাবে না। যদি রাফির ফোন বন্ধ থাকে, মেসেজটি তার জন্য অপেক্ষা করবে বা সার্ভারে স্টোর হয়ে থাকবে।
  • অর্ডারিং (Ordering): একটি কথোপকথন বা কনভারসেশনের মেসেজগুলো সঠিক ক্রমানুসারে (order) উপস্থিত হতে হবে।
  • স্কেল (Scale): প্রতিদিন প্রায় ৫০ মিলিয়ন (50M) সক্রিয় ব্যবহারকারী (Daily Active Users) এবং প্রতিদিন প্রায় ১ বিলিয়ন (1B) মেসেজ আদান-প্রদান হবে।
দুজন ব্যবহারকারী রিয়েল টাইমে চ্যাট করতে চান

ওয়েবসকেট (WebSockets) বনাম পোলিং (Polling) বনাম লং পোলিং (Long Polling)

চ্যাটের জন্য রিয়েল-টাইম, বাইডিরেকশনাল বা দ্বিমুখী যোগাযোগ (bidirectional communication) প্রয়োজন। সার্ভারকে অবিলম্বে ক্লায়েন্টদের কাছে মেসেজ পুশ (push) করতে হবে — ক্লায়েন্টের জিজ্ঞাসা বা রিকোয়েস্ট করা পর্যন্ত অপেক্ষা করা যাবে না। চলুন অপশনগুলো বা বিকল্পগুলোর তুলনা করে দেখি:

শর্ট পোলিং (Short Polling): ক্লায়েন্ট প্রতি কয়েক সেকেন্ড পর পর সার্ভারকে জিজ্ঞাসা করে, "নতুন কোনো মেসেজ আছে কি?" এটি একটি সহজ পদ্ধতি হলেও অত্যন্ত অপচয়মূলক — ৯৯% রিকোয়েস্টের উত্তর আসে "না, নতুন কিছু নেই।" এটি অনেকটা একটি বাচ্চার মতো যে দীর্ঘ যাত্রায় প্রতি ৩০ সেকেন্ড পর পর জিজ্ঞাসা করে, "আমরা কি পৌঁছে গেছি?"

লং পোলিং (Long Polling): ক্লায়েন্ট সার্ভারকে জিজ্ঞাসা করে, "নতুন কোনো মেসেজ আছে কি?" কিন্তু সার্ভার কানেকশনটিকে ধরে রাখে বা খোলা রাখে যতক্ষণ না রিটার্ন করার মতো কিছু থাকে (অথবা কানেকশনটির টাইমআউট না হয়)। এটি শর্ট পোলিংয়ের চেয়ে বেশ ভালো — কারণ এতে খালি বা এম্পটি (empty) রেসপন্স কম আসে। কিন্তু প্রতিটি "পোল (poll)" সার্ভারের একটি কানেকশন দখল বা আবদ্ধ (tie up) করে রাখে।

ওয়েবসকেটস (WebSockets): এটি ক্লায়েন্ট এবং সার্ভারের মধ্যে একটি স্থায়ী বা পারসিস্টেন্ট (persistent), দ্বিমুখী কানেকশন। একবার কানেকশন স্থাপিত হলে, যেকোনো পক্ষ যেকোনো সময় ডেটা পাঠাতে পারে। চ্যাটের জন্য এটি হলো গোল্ড স্ট্যান্ডার্ড বা সর্বোত্তম পদ্ধতি। এতে ল্যাটিনসি কম হয়, ওভারহেড (overhead) কম হয় এবং কোনো অপচয়মূলক রিকোয়েস্ট থাকে না।

এর ট্রেড-অফ (Trade-off) বা অসুবিধা: ওয়েবসকেট কানেকশনগুলো মূলত স্টেটফুল (stateful) — অর্থাৎ আপনাকে জানতে হবে কোন ব্যবহারকারী কোন সার্ভারের সাথে যুক্ত আছে। সাধারণ স্টেটলেস HTTP-এর তুলনায় এটি অতিরিক্ত বা এক্সট্রা জটিলতা তৈরি করে। আমরা দেখব এটি কীভাবে পরিচালনা করা যায়।

ওয়েবসকেট: একটি স্থায়ী দ্বিমুখী সংযোগ (persistent bidirectional connection)

একটি সাধারণ (Simple) ওয়েবসকেট চ্যাট সার্ভার

import asyncio
import websockets
import json
from collections import defaultdict
# Track connected users: user_id -> websocket connection
connected_users = {} # In production, use Redis pub/sub across servers
async def handle_connection(websocket, path):
user_id = None
try:
# First message should be an authentication message
auth_msg = await websocket.recv()
auth = json.loads(auth_msg)
user_id = auth["user_id"]
connected_users[user_id] = websocket
print(f"User {user_id} connected")
# Listen for messages
async for raw_message in websocket:
message = json.loads(raw_message)
recipient_id = message["to"]
content = message["content"]
timestamp = message["timestamp"]
# Build the message for delivery
outgoing = {
"from": user_id,
"content": content,
"timestamp": timestamp,
"message_id": f"{user_id}_{timestamp}"
}
# Store in database (async, don't block)
# await store_message(outgoing)
# Deliver if recipient is online
if recipient_id in connected_users:
await connected_users[recipient_id].send(
json.dumps(outgoing)
)
# Send a delivery receipt to the sender
await websocket.send(json.dumps({
"type": "delivered",
"message_id": outgoing["message_id"]
}))
else:
# User is offline — queue for push notification
# await push_notification_service.notify(recipient_id, outgoing)
print(f"User {recipient_id} offline — queuing notification")
finally:
if user_id and user_id in connected_users:
del connected_users[user_id]
print(f"User {user_id} disconnected")
# Start the server
# asyncio.run(websockets.serve(handle_connection, 'localhost', 8765))
print("Chat server ready on ws://localhost:8765")
Output
Chat server ready on ws://localhost:8765

হাই-লেভেল আর্কিটেকচার (High-Level Architecture)

চলুন কম্পোনেন্টগুলো বা অংশগুলো সাজাই:

চ্যাট সার্ভার (WebSocket): এগুলো স্থায়ী বা পারসিস্টেন্ট ওয়েবসকেট (WebSocket) কানেকশনগুলো হ্যান্ডেল করে। প্রতিটি সার্ভার হাজার হাজার সক্রিয় কানেকশন বা অ্যাক্টিভ কানেকশন পরিচালনা করে। যখন কোনো মেসেজ আসে, তখন চ্যাট সার্ভার খুঁজে বের করে যে প্রাপক বা রেসিপিয়েন্ট কোন সার্ভারের সাথে যুক্ত আছে।

কানেকশন রেজিস্ট্রি (Redis): এটি user_id → chat_server_id -এর ম্যাপিং স্টোর করে। যখন ব্যবহারকারী আনিকা সার্ভার ৩-এর সাথে সংযুক্ত হয়, তখন আমরা Redis-এ anika → server-3 লিখে বা স্টোর করে রাখি। যখন রাফি আনিকাকে মেসেজ পাঠায়, তখন আমরা আনিকার সার্ভারটি খুঁজে বের করি এবং সেখানে মেসেজ রাউট বা রুট (route) করি।

মেসেজ কিউ (Kafka): এটি মেসেজ পাঠানোকে প্রসেসিং থেকে ডিকাপল (decouple) বা আলাদা করে। যখন কোনো মেসেজ পাঠানো হয়, তখন এটি Kafka-এ পাবলিশ (publish) করা হয়। কনজ্যুমাররা স্বাধীনভাবে স্টোরেজ, ডেলিভারি এবং পুশ নোটিফিকেশনগুলো নিয়ন্ত্রণ করে।

মেসেজ স্টোরেজ (Message Storage): মেসেজগুলোকে অবশ্যই রিলায়েবল, ডিউরেবল বা টেকসই হতে হবে এবং যাতে আবার ফিরে পাওয়া যায় এমন হতে হবে। এখানে দুটি অপশন বা বিকল্প রয়েছে:

  • ১:১ চ্যাটের জন্য: (user_id, conversation_id, timestamp) দ্বারা কি (key) করা একটি কী-ভ্যালু (key-value) স্টোর। Cassandra এ কাজে বেশ মানানসই — এটি চমৎকার রাইট থ্রুপুট (write throughput) দেয় এবং টাইমস্ট্যাম্প দ্বারা চমৎকার রেঞ্জ কুয়েরি করতে পারে।
  • গ্রুপ চ্যাটের জন্য: (group_id, timestamp) দ্বারা মেসেজগুলো স্টোর করুন। এর ফলে প্রতিটি সদস্য তাদের গ্রুপের জন্য মেসেজগুলো রিট্রিভ (retrieve) বা উদ্ধার করতে পারে বা পড়তে পারে।

পুশ নোটিফিকেশন সার্ভিস: যখন কোনো ব্যবহারকারী অফলাইনে থাকেন, তখন APNs (iOS) বা FCM (Android) এর মাধ্যমে তাদের পুশ নোটিফিকেশন পাঠান। এটি একটি আলাদা সেবা যা মেসেজ কিউ (message queue) থেকে ডেটা ব্যবহার করে।

মেসেজ পাঠানো: আনিকা → সার্ভার → রাফি
Click chart to zoom
মেসেজ ডেলিভারির ফ্লো: অনলাইন ডেলিভারি ওয়েবসকেট রাউটিং এর মাধ্যমে, আর অফলাইন ব্যবহারকারীদের জন্য ফলব্যাক করা হয় পুশ নোটিফিকেশনের মাধ্যমে

মেসেজ অর্ডারিং এবং আইডি (Message Ordering and IDs)

মেসেজগুলো অবশ্যই সঠিক ক্রমানুসারে (order) প্রদর্শিত হতে হবে। কিন্তু একটি ডিস্ট্রিবিউটেড সিস্টেমের ক্ষেত্রে বিভিন্ন ডিভাইসের টাইমস্ট্যাম্পগুলো সিঙ্কে (sync) বা সমলয়ে নাও থাকতে পারে (অর্থাৎ ঘড়ির সময়ে পার্থক্য থাকতে পারে)। তাহলে আপনি কীভাবে সঠিক ক্রমানুসারের নিশ্চয়তা দেবেন?

সার্ভার-সাইড টাইমস্ট্যাম্প: এটি খুব সাধারণ পদ্ধতি। চ্যাট সার্ভার যখন মেসেজটি পায়, তখন এটি একটি টাইমস্ট্যাম্প অ্যাসাইন করে বা যুক্ত করে দেয়। এটি একটি মাত্র সার্ভারের জন্য ভালোভাবে কাজ করে কিন্তু একাধিক সার্ভার হলে এটি বেশ জটিল হয়ে যায় (কারণ তাদের ঘড়ির সময় কয়েক মিলিসেকেন্ড ভিন্ন হতে পারে)।

প্রতিটি কনভারসেশনের জন্য সিকোয়েন্স নাম্বার (Sequence numbers): প্রতিটি কথোপকথন বা কনভারসেশনে একটি স্বয়ংক্রিয়ভাবে ইনক্রিমেন্টিং (auto-incrementing) সিকোয়েন্স বা সিরিয়াল নম্বর থাকে। যেমন মেসেজ ১, ২, ৩, ৪... এটি একটি কনভারসেশনের মধ্যে নিখুঁত অর্ডারিং বা ক্রম গ্যারান্টি দেয়। দ্রুত এই নম্বর বাড়ানোর জন্য সর্বশেষ সিকোয়েন্স নম্বরটি Redis-এ স্টোর করে রাখা হয়।

স্নোফ্লেক আইডি (Snowflake IDs): টুইটারের (Twitter) স্নোফ্লেক আইডি গ্লোবালভাবে ইউনিক, টাইম-অর্ডার করা বা সময় ভিত্তিক সাজানো আইডি তৈরি করে। প্রতিটি আইডিতে time-stamp (41 bits) + machine_id (10 bits) + sequence (12 bits) এনকোড করা থাকে। এর আইডিগুলো সময়ের উপর ভিত্তি করে ক্রমানুসারে সাজানো যায় (sortable), সমস্ত মেশিনের মধ্যে ইউনিক বা অনন্য থাকে এবং অন্য সার্ভারের সমন্বয় ছাড়াই তৈরি করা যায়।

অনলাইন/অফলাইন স্ট্যাটাস (Online/Offline Status)

কীভাবে বুঝবেন কোনো ব্যক্তি "অনলাইন" আছেন কি না? এর জন্য দুটি পদ্ধতি রয়েছে:

হার্টবিট-বেসড (Heartbeat-based - স্পন্দন-ভিত্তিক): প্রতিটি কানেকটেড বা সংযুক্ত ক্লায়েন্ট প্রতি ৩০ সেকেন্ডে একটি করে "হার্টবিট" (a tiny ping বা ছোট একটি সিগন্যাল) পাঠায়। সার্ভার সর্বশেষ হার্টবিটের সময়টি রেকর্ড বা সংরক্ষণ করে। যদি সর্বশেষ হার্টবিট ৬০ সেকেন্ডের চেয়েও পুরনো হয়, তবে ব্যবহারকারীকে অফলাইন হিসেবে বিবেচনা করা হয়।

সর্বশেষ দেখার (last-seen) টাইমস্ট্যাম্পগুলো রেডিজ (Redis)-এ সংরক্ষণ করুন: user:42:last_seen → 1640000000। "অনলাইন" বা "৫ মিনিট আগে দেখা গেছে (Last seen 5 min ago)" দেখানোর জন্য এটি ব্যবহার করতে পারেন।

গ্রুপ চ্যাটের ক্ষেত্রে: কেউ অনলাইনে আসলে বা অফলাইনে গেলে ৫০০ সদস্যের সবাইকে একই সাথে অনলাইন স্ট্যাটাস দেখানো সিস্টেমের বেশ লোড সৃষ্টি করবে (এটা বেশ চ্যাটি বা অতিরিক্ত কথা বলার মতো হয়ে যাবে)। এর সমাধান: শুধুমাত্র যখন কোনও ব্যবহারকারী নির্দিষ্ট একটি চ্যাট ওপেন বা খুলবে, তখনই অনলাইন স্ট্যাটাস দেখান। ক্রমাগতভাবে পুশ (push) না করে, প্রয়োজন হলে বা অন-ডিমান্ড (on demand) অবস্থা থেকে স্ট্যাটাস ফেচ (fetch) করুন বা তুলে আনুন।

গ্রুপ চ্যাট: দলের বা গ্রুপের সব সদস্যের মধ্যে তথ্য ছড়ানো (fan-out)

রিড রিসিট (Read Receipts - পড়ার রশিদ)

রিড রিসিট ("ডেলিভারড" ✓ এবং "পড়া হয়েছে" ✓✓) সিস্টেমে আরও একটি লেয়ার বা স্তর যুক্ত করে:

  • সেন্ড (Sent - পাঠানো হয়েছে): সার্ভার বা আপনার মেসেজটি পেয়েছে (প্রেরকের কাছে এটি নিশ্চিত বা নিশ্চিতকরণ করা হয়েছে)।
  • ডেলিভারড (Delivered - পৌঁছে দেওয়া হয়েছে): প্রাপকের বা যার কাছে পাঠাচ্ছেন তার ডিভাইসটি মেসেজ পেয়েছে (প্রাপকের ডিভাইস বা ক্লায়েন্ট নিশ্চিত করে এটি সার্ভারকে বলবে)।
  • রিড (Read - পড়া হয়েছে): প্রাপক চ্যাট ওপেন করেছে (ব্যবহারকারী যখন কথোপকথন বা মেসেজটি দেখে তখন ক্লায়েন্ট বা তার ডিভাইস একটি "রিড (read)" ইভেন্ট সার্ভারকে পাঠায়)।

১:১ চ্যাটের ক্ষেত্রে এটি খুব সহজ — প্রতিটি মেসেজের জন্য একটি মাত্র নিশ্চিতকরণ বা অ্যাকনোলেজমেন্ট (acknowledgment)। তবে গ্রুপ চ্যাটের ক্ষেত্রে, কে মেসেজটি পড়েছে তা ট্র্যাক করা বেশ ব্যয়বহুল বা কঠিন। হোয়াটসঅ্যাপ এই সমস্যাটির সমাধান করেছে একটি চালাকির মাধ্যমে, আপনি যখন মেসেজটির উপর ট্যাপ করে ধরে রাখেন শুধুমাত্র তখনই রিড ইনফো (read info) বা বিস্তারিত তথ্য দেখায় — এটি রিয়েল-টাইমে সবার জন্য ট্র্যাক করার পরিবর্তে যখন প্রয়োজন বা অন-ডিমান্ড (on demand) হয়, তখনই তথ্যটি ফেচ (fetch) করে নিয়ে আসে।

Note: চ্যাট সিস্টেমটিকে একটি পোস্ট অফিসের মতো ভাবতে পারেন। ওয়েবসকেট হলো প্রতিটি ব্যক্তির সাথে আপনার একটি ডাইরেক্ট টেলিফোন বা সরাসরি ফোন লাইনের মতো — তাৎক্ষণিক যোগাযোগ। মেসেজ কিউ হলো জিনিসপত্র সর্টিং বা সাজানোর ঘর — মেসেজগুলো আসে, সাজানো হয় এবং সঠিক গন্তব্যে পাঠানো হয়। ডাটাবেস হলো আপনার ফাইলিং ক্যাবিনেট — যেখান থেকে আপনি সবসময় পুরনো চিঠিগুলো ফিরে পেতে পারেন। পুশ নোটিফিকেশন হলো সেই সব লোকেদের জন্য বাহক বা পিজিয়ন (pigeon) যারা তখন বাড়িতে থাকে না (অফলাইনে থাকে)।
পূর্ণাঙ্গ আর্কিটেকচার: WS সার্ভার, মেসেজ কিউ (Message Queue) এবং স্টোরেজ

চ্যাট সিস্টেম স্কেলিং করা

প্রতিদিন ৫০ (50M) মিলিয়ন অ্যাক্টিভ ইউজার ১ (1B) বিলিয়ন মেসেজ পাঠালে, সেকেন্ডে প্রায় ১২,০০০ মেসেজ পাঠানো হয় (12,000 messages/sec)। সর্বোচ্চ চাপের সময়ে (peak) এটি ৩ গুণ বেড়ে প্রায় ৩৬,০০০ মেসেজ প্রতি সেকেন্ডে পৌঁছাতে পারে। সিস্টেমের প্রতিটি অংশ কীভাবে স্কেল করা যায় তা নিচে দেওয়া হলো:

  • চ্যাট সার্ভার: প্রতিটি সার্ভার প্রায় ১০,০০০ সমসাময়িক ওয়েবসকেট কানেকশন হ্যান্ডেল করে। ৫০ (50M) মিলিয়ন অ্যাক্টিভ ইউজারের (সম্ভবত এর মধ্যে ১০ মিলিয়ন একসাথে অনলাইনে থাকে) জন্য, আপনার প্রায় ১,০০০টি চ্যাট সার্ভার প্রয়োজন হবে। কনসিস্টেন্ট হ্যাশিং (Consistent hashing) ব্যবহার করে ব্যবহারকারীদের সার্ভারের সাথে অ্যাসাইন বা যুক্ত করুন।
  • রেডিজ (Redis - কানেকশন রেজিস্ট্রি): এটি এমন একটি রেডিজ ক্লাস্টার যা ইউজার→সার্ভার (user→server) ম্যাপিং স্টোর করে। ১০ মিলিয়ন ছোট মানের এন্ট্রি খুব অনায়াসেই এর মেমোরিতে জায়গা করে নিতে পারে।
  • কাফকা (Kafka): কনভারসেশন আইডি (conversation_id) ব্যবহার করে মেসেজ টপিকগুলোকে পার্টিশন বা ভাগ করুন, যাতে একটি কনভারসেশনের সমস্ত মেসেজ একই পার্টিশনে ক্রমানুসারে থাকে।
  • ক্যাসান্ড্রা (Cassandra - মেসেজ স্টোরেজ): কনভারসেশন আইডি (conversation_id) দিয়ে পার্টিশন করুন এবং টাইমস্ট্যাম্প (timestamp) দিয়ে ক্লাস্টার করুন। এটি আপনার লেখার কাজকে (writes) অত্যন্ত দ্রুত করবে এবং পুরনো মেসেজ পড়ার বা হিস্টরি রিট্রিভাল অনেক ফাস্ট বা দ্রুত করে তুলবে।
Note: ইন্টারভিউ টিপস: সব চ্যাট সিস্টেম ডিজাইনেই যে জিনিসটি সবচেয়ে বেশি লক্ষ্য করা হয় তা হলো কানেকশন রেজিস্ট্রি। হাজার হাজার স্টেটফুল ওয়েবসকেট সার্ভারের মধ্যে, ব্যবহারকারী ঠিক কোন সার্ভারে রয়েছে তা খুঁজে বের করার একটি কার্যকর উপায় আপনার কাছে অবশ্যই থাকতে হবে। এখানে Redis হলো স্ট্যান্ডার্ড এবং ডিফল্ট সমাধান। এছাড়াও, সবসময় অফলাইন প্রক্রিয়ার কথা উল্লেখ করতে ভুলবেন না — অফলাইন ব্যবহারকারীদের জন্য পুশ নোটিফিকেশনের ব্যবস্থা করা রিয়েল-টাইম ওয়েবসকেট প্রক্রিয়ার মতোই সমান গুরুত্বপূর্ণ।

Key Metrics

ওয়েবসকেট মেসেজ ডেলিভারি
অনলাইন ব্যবহারকারীদের জন্য এন্ড-টু-এন্ড প্রসেস
~১০-৫০ ms \(O(1)\)
রেডিজে (Redis) ব্যবহারকারী বা ইউজার লুকআপ
ব্যবহারকারীর ওয়েবসকেট সার্ভার খুঁজে পাওয়া
< ১ ms \(O(1)\)
মেসেজ স্টোরেজ (Cassandra)
অ্যাপেন্ড-অপ্টিমাইজড (Append-optimized) বা যুক্ত করার জন্য অপ্টিমাইজড
~১-৫ ms \(O(1)\)
মেসেজ হিস্টরি লোড করা
k = প্রতি পেজে মেসেজের পরিমাণ
~৫-২০ ms \(O(k)\)
গ্রুপ মেসেজ ফ্যান-আউট (Group message fan-out) (৫০০ জন সদস্য)
n = গ্রুপের সাইজ বা আকার
~৫০-২০০ ms \(O(n)\)
পুশ নোটিফিকেশন ডেলিভারি
APNs/FCM এর রেসপন্সের ওপর নির্ভর করে
~১০০-৩০০০ ms \(O(1)\)

ছোট কুইজ

চ্যাট অ্যাপ্লিকেশনের জন্য শর্ট পোলিংয়ের (short polling) চেয়ে ওয়েবসকেট (WebSockets) কেন বেশি পছন্দ করা হয়?

পড়া চালিয়ে যান

নোটিফিকেশন সিস্টেম ডিজাইন (Design a Notification System)
সঠিক বার্তা, সঠিক ব্যক্তির কাছে, সঠিক সময়ে
মেসেজ কিউ (Message Queues)
সবকিছু এখনই করবেন না — লাইনে দাঁড় করিয়ে দিন
স্কেলেবিলিটি (Scalability)
এক ইউজার থেকে এক বিলিয়ন — সিস্টেম কীভাবে বড় হয়
নিউজ ফিড ডিজাইন (Design a News Feed)
লক্ষ লক্ষ মানুষকে তাৎক্ষণিকভাবে পার্সোনালাইজড কন্টেন্ট সরবরাহ করা