# Low Level Design: Online Status Service

Source: https://www.techinterview.org/post/3233471607/lld-online-status/
Updated: 2026-06-30 · techinterview.org

## What Is an Online Status Service?

An online status service exposes a queryable view of whether users are currently active, idle, or offline. Unlike a raw presence service that manages connection-level state, an online status service adds a semantic layer: it aggregates multi-device presence, applies user-defined visibility rules (e.g., appear offline), and serves status queries from other services such as friend lists, profile pages, and notification routing. It is a read-heavy, eventually consistent system where slight staleness is acceptable.

## Data Model

Three storage tiers serve different access patterns.

### Redis (hot read cache)


```
status:{user_id}            HASH    fields: status, last_active_ms, device_count
status:visible:{user_id}    STRING  value = 'true' | 'false', no TTL (user preference)
status:bulk:{shard}         ZSET    score = last_active_ms, member = user_id
```


### SQL Schema


```
CREATE TABLE user_status (
    user_id          BIGINT PRIMARY KEY,
    status           ENUM('online','idle','offline') NOT NULL DEFAULT 'offline',
    last_active_at   TIMESTAMP NOT NULL,
    device_count     SMALLINT NOT NULL DEFAULT 0,
    visible          BOOLEAN NOT NULL DEFAULT TRUE,
    updated_at       TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_last_active (last_active_at)
);
```


## Core Algorithm: Aggregation and Idle Detection

A user may be logged in on multiple devices simultaneously. The status service must synthesize a single canonical status.

  - **Presence events arrive** from the underlying presence service via Kafka topic `presence.updates`.

  - **Status aggregator** reads the current `device_count` from Redis. On a `session_connected` event it increments the counter; on `session_disconnected` it decrements. Status transitions to `offline` only when `device_count` reaches zero.

  - **Idle detection:** A background job scans the `status:bulk:{shard}` sorted set for users whose `last_active_ms` score is older than 5 minutes. It transitions those users to `idle` by updating their Redis hash and publishing a `status_changed` event.

  - **Visibility filter:** Before any status is returned to callers the service checks `status:visible:{user_id}`. If the user has chosen to appear offline the API always returns `offline` regardless of true status.

## Read Path: Bulk Status Queries

Friend lists, contact pages, and notification services query the status of many users in a single call. The read path is optimized for bulk access:

  - Caller sends a list of up to 1,000 user IDs.

  - Status service issues a Redis `HMGET` pipeline across the relevant `status:{user_id}` hashes in a single round trip.

  - Cache misses (cold users) are fetched from SQL in a single `WHERE user_id IN (...)` query and backfilled into Redis with a 60-second TTL.

  - Results are filtered through visibility rules before being returned.

## Failure Handling

  - **Aggregator crash:** Kafka consumer group re-balances and the aggregator replays from the last committed offset. Because status transitions are idempotent (setting the same status twice has no net effect), replay is safe.

  - **Redis unavailability:** The service falls back to SQL for reads and queues writes to a local buffer (or a secondary Redis replica). A brief period of stale status data is acceptable.

  - **Idle scanner failure:** Users remain in `online` state longer than intended. The impact is cosmetic; correctness is restored when the scanner recovers or the presence service eventually sends an `offline` event.

  - **Split-brain multi-device:** If two devices send conflicting events concurrently, a compare-and-swap on the `device_count` field with Redis WATCH/MULTI prevents counter corruption.

## Scalability Considerations

The online status service is read-heavy: status is written once per session event but read thousands of times per second for friend lists, badge counts, and routing decisions.

  - **Read replicas:** Route all bulk read queries to Redis read replicas. Replicate SQL status table to read replicas for fallback queries.

  - **Sharded aggregators:** Partition the `presence.updates` Kafka topic by `user_id mod N`. Each aggregator shard owns a non-overlapping set of user IDs, eliminating cross-shard coordination.

  - **CDN-cached public profiles:** For public-facing status (e.g., creator profiles), cache the status response at the CDN edge with a 30-second TTL. This absorbs spikes without hitting the origin.

  - **Rate-limit polling clients:** Mobile clients that poll status via REST rather than maintaining a WebSocket are throttled to one request per 30 seconds per user to prevent thundering-herd patterns.

## Summary

An online status service sits above raw presence data and adds multi-device aggregation, idle detection, visibility controls, and a bulk-read-optimized query layer. Redis is the primary store for hot status data; SQL provides durability and fallback. Kafka decouples the write path (status aggregation) from the read path (query serving), allowing each to scale independently. The result is an eventually consistent, horizontally scalable service capable of serving millions of status queries per second with sub-10-millisecond p99 latency.

See also: [Meta Interview Guide 2026: Facebook, Instagram, WhatsApp Engineering](https://www.techinterview.org/post/3233460272/meta-interview-guide-2026-facebook-instagram-whatsapp-engineering/)

See also: [LinkedIn Interview Guide 2026: Social Graph Engineering, Feed Ranking, and Professional Network Scale](https://www.techinterview.org/post/3233460278/linkedin-interview-guide-2026-social-graph-engineering-feed-ranking-and-professional-network-scale/)

See also: [Snap Interview Guide](https://www.techinterview.org/post/3233459923/snap-interview/)
