System Design enthusiasts! 👋 If you are building a chat application and want to support millions of active users like WhatsApp or Telegram, here are the key details of 'Last Seen' tracking that differentiate junior developers from senior engineers:
1️⃣ Never update the database with every user activity! 🛑
This is a critical mistake. If you have 10 million active users, writing every single presence update directly to your database will create massive write bottlenecks and crash the system. Write operations are expensive; minimize them as much as possible.
2️⃣ The In-Memory Solution: Redis 🚀
Split your architecture into two layers: Real-time presence and Historical storage. For the active 'Online Status', store it in Redis with an Expiration TTL (e.g., 120 seconds) using commands like `SETEX`. As long as the user interacts, renew the key. If they close the app, the key naturally expires.
3️⃣ Smart Database Updates (Time Buffering) 🕰️
To maintain a historical 'Last Seen' timestamp, update the database in batches, not in real-time. For example, only write to the database if the user's cached status is older than 5 minutes: `WHERE last_seen < NOW() - 5 MIN`. This reduces database write loads by up to 80%!
4️⃣ Read Path: Caching First 🕵️♂️
When showing status to other users, query Redis first. If the key exists, render 'Online Now'. If not, fetch the last seen timestamp from the database and display 'Last seen X minutes ago'. This saves millions of database hits.
5️⃣ Offloading with Batch Background Jobs 😎
Instead of running a single update query per user, collect presence updates in a background queue and run a bulk update query once every minute. This allows the database to breathe and ensures extreme performance.
6️⃣ Privacy and UX 🛡️
If a user toggles 'Don't show last seen', disable tracking entirely. Additionally, cache database read results for a minute so that opening a profile repeatedly doesn't hit the database every single time.